Updated script that can be controled by Nodejs web app

This commit is contained in:
mac OS
2024-11-25 12:24:18 +07:00
parent c440eda1f4
commit 8b0ab2bd3a
8662 changed files with 1803808 additions and 34 deletions

View File

@ -0,0 +1,3 @@
import { Socket } from "./socket.js";
declare const _default: (uri: any, opts: any) => Socket;
export default _default;

View File

@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const socket_js_1 = require("./socket.js");
exports.default = (uri, opts) => new socket_js_1.Socket(uri, opts);

View File

@ -0,0 +1 @@
export declare const hasCORS: boolean;

View File

@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hasCORS = void 0;
// imported from https://github.com/component/has-cors
let value = false;
try {
value = typeof XMLHttpRequest !== 'undefined' &&
'withCredentials' in new XMLHttpRequest();
}
catch (err) {
// if XMLHttp support is disabled in IE then it will throw
// when trying to create
}
exports.hasCORS = value;

View File

@ -0,0 +1,15 @@
/**
* Compiles a querystring
* Returns string representation of the object
*
* @param {Object}
* @api private
*/
export declare function encode(obj: any): string;
/**
* Parses a simple querystring into an object
*
* @param {String} qs
* @api private
*/
export declare function decode(qs: any): {};

View File

@ -0,0 +1,38 @@
"use strict";
// imported from https://github.com/galkn/querystring
/**
* Compiles a querystring
* Returns string representation of the object
*
* @param {Object}
* @api private
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.encode = encode;
exports.decode = decode;
function encode(obj) {
let str = '';
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
if (str.length)
str += '&';
str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
}
}
return str;
}
/**
* Parses a simple querystring into an object
*
* @param {String} qs
* @api private
*/
function decode(qs) {
let qry = {};
let pairs = qs.split('&');
for (let i = 0, l = pairs.length; i < l; i++) {
let pair = pairs[i].split('=');
qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
return qry;
}

View File

@ -0,0 +1 @@
export declare function parse(str: string): any;

View File

@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parse = parse;
// imported from https://github.com/galkn/parseuri
/**
* Parses a URI
*
* Note: we could also have used the built-in URL object, but it isn't supported on all platforms.
*
* See:
* - https://developer.mozilla.org/en-US/docs/Web/API/URL
* - https://caniuse.com/url
* - https://www.rfc-editor.org/rfc/rfc3986#appendix-B
*
* History of the parse() method:
* - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c
* - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3
* - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242
*
* @author Steven Levithan <stevenlevithan.com> (MIT license)
* @api private
*/
const re = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
const parts = [
'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
];
function parse(str) {
if (str.length > 8000) {
throw "URI too long";
}
const src = str, b = str.indexOf('['), e = str.indexOf(']');
if (b != -1 && e != -1) {
str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
}
let m = re.exec(str || ''), uri = {}, i = 14;
while (i--) {
uri[parts[i]] = m[i] || '';
}
if (b != -1 && e != -1) {
uri.source = src;
uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
uri.ipv6uri = true;
}
uri.pathNames = pathNames(uri, uri['path']);
uri.queryKey = queryKey(uri, uri['query']);
return uri;
}
function pathNames(obj, path) {
const regx = /\/{2,9}/g, names = path.replace(regx, "/").split("/");
if (path.slice(0, 1) == '/' || path.length === 0) {
names.splice(0, 1);
}
if (path.slice(-1) == '/') {
names.splice(names.length - 1, 1);
}
return names;
}
function queryKey(uri, query) {
const data = {};
query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {
if ($1) {
data[$1] = $2;
}
});
return data;
}

4
node_modules/engine.io-client/build/cjs/globals.d.ts generated vendored Normal file
View File

@ -0,0 +1,4 @@
export declare const nextTick: (cb: any, setTimeoutFn: any) => any;
export declare const globalThisShim: any;
export declare const defaultBinaryType = "arraybuffer";
export declare function createCookieJar(): void;

26
node_modules/engine.io-client/build/cjs/globals.js generated vendored Normal file
View File

@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultBinaryType = exports.globalThisShim = exports.nextTick = void 0;
exports.createCookieJar = createCookieJar;
exports.nextTick = (() => {
const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
if (isPromiseAvailable) {
return (cb) => Promise.resolve().then(cb);
}
else {
return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
}
})();
exports.globalThisShim = (() => {
if (typeof self !== "undefined") {
return self;
}
else if (typeof window !== "undefined") {
return window;
}
else {
return Function("return this")();
}
})();
exports.defaultBinaryType = "arraybuffer";
function createCookieJar() { }

View File

@ -0,0 +1,21 @@
export declare const nextTick: (callback: Function, ...args: any[]) => void;
export declare const globalThisShim: typeof globalThis;
export declare const defaultBinaryType = "nodebuffer";
export declare function createCookieJar(): CookieJar;
interface Cookie {
name: string;
value: string;
expires?: Date;
}
/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
*/
export declare function parse(setCookieString: string): Cookie;
export declare class CookieJar {
private _cookies;
parseCookies(values: string[]): void;
get cookies(): IterableIterator<[string, Cookie]>;
addCookies(xhr: any): void;
appendCookies(headers: Headers): void;
}
export {};

View File

@ -0,0 +1,97 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CookieJar = exports.defaultBinaryType = exports.globalThisShim = exports.nextTick = void 0;
exports.createCookieJar = createCookieJar;
exports.parse = parse;
exports.nextTick = process.nextTick;
exports.globalThisShim = global;
exports.defaultBinaryType = "nodebuffer";
function createCookieJar() {
return new CookieJar();
}
/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
*/
function parse(setCookieString) {
const parts = setCookieString.split("; ");
const i = parts[0].indexOf("=");
if (i === -1) {
return;
}
const name = parts[0].substring(0, i).trim();
if (!name.length) {
return;
}
let value = parts[0].substring(i + 1).trim();
if (value.charCodeAt(0) === 0x22) {
// remove double quotes
value = value.slice(1, -1);
}
const cookie = {
name,
value,
};
for (let j = 1; j < parts.length; j++) {
const subParts = parts[j].split("=");
if (subParts.length !== 2) {
continue;
}
const key = subParts[0].trim();
const value = subParts[1].trim();
switch (key) {
case "Expires":
cookie.expires = new Date(value);
break;
case "Max-Age":
const expiration = new Date();
expiration.setUTCSeconds(expiration.getUTCSeconds() + parseInt(value, 10));
cookie.expires = expiration;
break;
default:
// ignore other keys
}
}
return cookie;
}
class CookieJar {
constructor() {
this._cookies = new Map();
}
parseCookies(values) {
if (!values) {
return;
}
values.forEach((value) => {
const parsed = parse(value);
if (parsed) {
this._cookies.set(parsed.name, parsed);
}
});
}
get cookies() {
const now = Date.now();
this._cookies.forEach((cookie, name) => {
var _a;
if (((_a = cookie.expires) === null || _a === void 0 ? void 0 : _a.getTime()) < now) {
this._cookies.delete(name);
}
});
return this._cookies.entries();
}
addCookies(xhr) {
const cookies = [];
for (const [name, cookie] of this.cookies) {
cookies.push(`${name}=${cookie.value}`);
}
if (cookies.length) {
xhr.setDisableHeaderCheck(true);
xhr.setRequestHeader("cookie", cookies.join("; "));
}
}
appendCookies(headers) {
for (const [name, cookie] of this.cookies) {
headers.append("cookie", `${name}=${cookie.value}`);
}
}
}
exports.CookieJar = CookieJar;

15
node_modules/engine.io-client/build/cjs/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,15 @@
import { Socket } from "./socket.js";
export { Socket };
export { SocketOptions, SocketWithoutUpgrade, SocketWithUpgrade, } from "./socket.js";
export declare const protocol: number;
export { Transport, TransportError } from "./transport.js";
export { transports } from "./transports/index.js";
export { installTimerFunctions } from "./util.js";
export { parse } from "./contrib/parseuri.js";
export { nextTick } from "./globals.node.js";
export { Fetch } from "./transports/polling-fetch.js";
export { XHR as NodeXHR } from "./transports/polling-xhr.node.js";
export { XHR } from "./transports/polling-xhr.js";
export { WS as NodeWebSocket } from "./transports/websocket.node.js";
export { WS as WebSocket } from "./transports/websocket.js";
export { WT as WebTransport } from "./transports/webtransport.js";

32
node_modules/engine.io-client/build/cjs/index.js generated vendored Normal file
View File

@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebTransport = exports.WebSocket = exports.NodeWebSocket = exports.XHR = exports.NodeXHR = exports.Fetch = exports.nextTick = exports.parse = exports.installTimerFunctions = exports.transports = exports.TransportError = exports.Transport = exports.protocol = exports.SocketWithUpgrade = exports.SocketWithoutUpgrade = exports.Socket = void 0;
const socket_js_1 = require("./socket.js");
Object.defineProperty(exports, "Socket", { enumerable: true, get: function () { return socket_js_1.Socket; } });
var socket_js_2 = require("./socket.js");
Object.defineProperty(exports, "SocketWithoutUpgrade", { enumerable: true, get: function () { return socket_js_2.SocketWithoutUpgrade; } });
Object.defineProperty(exports, "SocketWithUpgrade", { enumerable: true, get: function () { return socket_js_2.SocketWithUpgrade; } });
exports.protocol = socket_js_1.Socket.protocol;
var transport_js_1 = require("./transport.js");
Object.defineProperty(exports, "Transport", { enumerable: true, get: function () { return transport_js_1.Transport; } });
Object.defineProperty(exports, "TransportError", { enumerable: true, get: function () { return transport_js_1.TransportError; } });
var index_js_1 = require("./transports/index.js");
Object.defineProperty(exports, "transports", { enumerable: true, get: function () { return index_js_1.transports; } });
var util_js_1 = require("./util.js");
Object.defineProperty(exports, "installTimerFunctions", { enumerable: true, get: function () { return util_js_1.installTimerFunctions; } });
var parseuri_js_1 = require("./contrib/parseuri.js");
Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return parseuri_js_1.parse; } });
var globals_node_js_1 = require("./globals.node.js");
Object.defineProperty(exports, "nextTick", { enumerable: true, get: function () { return globals_node_js_1.nextTick; } });
var polling_fetch_js_1 = require("./transports/polling-fetch.js");
Object.defineProperty(exports, "Fetch", { enumerable: true, get: function () { return polling_fetch_js_1.Fetch; } });
var polling_xhr_node_js_1 = require("./transports/polling-xhr.node.js");
Object.defineProperty(exports, "NodeXHR", { enumerable: true, get: function () { return polling_xhr_node_js_1.XHR; } });
var polling_xhr_js_1 = require("./transports/polling-xhr.js");
Object.defineProperty(exports, "XHR", { enumerable: true, get: function () { return polling_xhr_js_1.XHR; } });
var websocket_node_js_1 = require("./transports/websocket.node.js");
Object.defineProperty(exports, "NodeWebSocket", { enumerable: true, get: function () { return websocket_node_js_1.WS; } });
var websocket_js_1 = require("./transports/websocket.js");
Object.defineProperty(exports, "WebSocket", { enumerable: true, get: function () { return websocket_js_1.WS; } });
var webtransport_js_1 = require("./transports/webtransport.js");
Object.defineProperty(exports, "WebTransport", { enumerable: true, get: function () { return webtransport_js_1.WT; } });

10
node_modules/engine.io-client/build/cjs/package.json generated vendored Normal file
View File

@ -0,0 +1,10 @@
{
"name": "engine.io-client",
"type": "commonjs",
"browser": {
"ws": false,
"./transports/polling-xhr.node.js": "./transports/polling-xhr.js",
"./transports/websocket.node.js": "./transports/websocket.js",
"./globals.node.js": "./globals.js"
}
}

482
node_modules/engine.io-client/build/cjs/socket.d.ts generated vendored Normal file
View File

@ -0,0 +1,482 @@
import { Emitter } from "@socket.io/component-emitter";
import type { Packet, BinaryType, RawData } from "engine.io-parser";
import { CloseDetails, Transport } from "./transport.js";
import { CookieJar } from "./globals.node.js";
export interface SocketOptions {
/**
* The host that we're connecting to. Set from the URI passed when connecting
*/
host?: string;
/**
* The hostname for our connection. Set from the URI passed when connecting
*/
hostname?: string;
/**
* If this is a secure connection. Set from the URI passed when connecting
*/
secure?: boolean;
/**
* The port for our connection. Set from the URI passed when connecting
*/
port?: string | number;
/**
* Any query parameters in our uri. Set from the URI passed when connecting
*/
query?: {
[key: string]: any;
};
/**
* `http.Agent` to use, defaults to `false` (NodeJS only)
*
* Note: the type should be "undefined | http.Agent | https.Agent | false", but this would break browser-only clients.
*
* @see https://nodejs.org/api/http.html#httprequestoptions-callback
*/
agent?: string | boolean;
/**
* Whether the client should try to upgrade the transport from
* long-polling to something better.
* @default true
*/
upgrade?: boolean;
/**
* Forces base 64 encoding for polling transport even when XHR2
* responseType is available and WebSocket even if the used standard
* supports binary.
*/
forceBase64?: boolean;
/**
* The param name to use as our timestamp key
* @default 't'
*/
timestampParam?: string;
/**
* Whether to add the timestamp with each transport request. Note: this
* is ignored if the browser is IE or Android, in which case requests
* are always stamped
* @default false
*/
timestampRequests?: boolean;
/**
* A list of transports to try (in order). Engine.io always attempts to
* connect directly with the first one, provided the feature detection test
* for it passes.
*
* @default ['polling','websocket', 'webtransport']
*/
transports?: ("polling" | "websocket" | "webtransport" | string)[] | TransportCtor[];
/**
* Whether all the transports should be tested, instead of just the first one.
*
* If set to `true`, the client will first try to connect with HTTP long-polling, and then with WebSocket in case of
* failure, and finally with WebTransport if the previous attempts have failed.
*
* If set to `false` (default), if the connection with HTTP long-polling fails, then the client will not test the
* other transports and will abort the connection.
*
* @default false
*/
tryAllTransports?: boolean;
/**
* If true and if the previous websocket connection to the server succeeded,
* the connection attempt will bypass the normal upgrade process and will
* initially try websocket. A connection attempt following a transport error
* will use the normal upgrade process. It is recommended you turn this on
* only when using SSL/TLS connections, or if you know that your network does
* not block websockets.
* @default false
*/
rememberUpgrade?: boolean;
/**
* Timeout for xhr-polling requests in milliseconds (0) (only for polling transport)
*/
requestTimeout?: number;
/**
* Transport options for Node.js client (headers etc)
*/
transportOptions?: Object;
/**
* (SSL) Certificate, Private key and CA certificates to use for SSL.
* Can be used in Node.js client environment to manually specify
* certificate information.
*/
pfx?: string;
/**
* (SSL) Private key to use for SSL. Can be used in Node.js client
* environment to manually specify certificate information.
*/
key?: string;
/**
* (SSL) A string or passphrase for the private key or pfx. Can be
* used in Node.js client environment to manually specify certificate
* information.
*/
passphrase?: string;
/**
* (SSL) Public x509 certificate to use. Can be used in Node.js client
* environment to manually specify certificate information.
*/
cert?: string;
/**
* (SSL) An authority certificate or array of authority certificates to
* check the remote host against.. Can be used in Node.js client
* environment to manually specify certificate information.
*/
ca?: string | string[];
/**
* (SSL) A string describing the ciphers to use or exclude. Consult the
* [cipher format list]
* (http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT) for
* details on the format.. Can be used in Node.js client environment to
* manually specify certificate information.
*/
ciphers?: string;
/**
* (SSL) If true, the server certificate is verified against the list of
* supplied CAs. An 'error' event is emitted if verification fails.
* Verification happens at the connection level, before the HTTP request
* is sent. Can be used in Node.js client environment to manually specify
* certificate information.
*/
rejectUnauthorized?: boolean;
/**
* Headers that will be passed for each request to the server (via xhr-polling and via websockets).
* These values then can be used during handshake or for special proxies.
*/
extraHeaders?: {
[header: string]: string;
};
/**
* Whether to include credentials (cookies, authorization headers, TLS
* client certificates, etc.) with cross-origin XHR polling requests
* @default false
*/
withCredentials?: boolean;
/**
* Whether to automatically close the connection whenever the beforeunload event is received.
* @default false
*/
closeOnBeforeunload?: boolean;
/**
* Whether to always use the native timeouts. This allows the client to
* reconnect when the native timeout functions are overridden, such as when
* mock clocks are installed.
* @default false
*/
useNativeTimers?: boolean;
/**
* Whether the heartbeat timer should be unref'ed, in order not to keep the Node.js event loop active.
*
* @see https://nodejs.org/api/timers.html#timeoutunref
* @default false
*/
autoUnref?: boolean;
/**
* parameters of the WebSocket permessage-deflate extension (see ws module api docs). Set to false to disable.
* @default false
*/
perMessageDeflate?: {
threshold: number;
};
/**
* The path to get our client file from, in the case of the server
* serving it
* @default '/engine.io'
*/
path?: string;
/**
* Whether we should add a trailing slash to the request path.
* @default true
*/
addTrailingSlash?: boolean;
/**
* Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols,
* so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to
* be able to handle different types of interactions depending on the specified protocol)
* @default []
*/
protocols?: string | string[];
}
type TransportCtor = {
new (o: any): Transport;
};
type BaseSocketOptions = Omit<SocketOptions, "transports"> & {
transports: TransportCtor[];
};
interface HandshakeData {
sid: string;
upgrades: string[];
pingInterval: number;
pingTimeout: number;
maxPayload: number;
}
interface SocketReservedEvents {
open: () => void;
handshake: (data: HandshakeData) => void;
packet: (packet: Packet) => void;
packetCreate: (packet: Packet) => void;
data: (data: RawData) => void;
message: (data: RawData) => void;
drain: () => void;
flush: () => void;
heartbeat: () => void;
ping: () => void;
pong: () => void;
error: (err: string | Error) => void;
upgrading: (transport: Transport) => void;
upgrade: (transport: Transport) => void;
upgradeError: (err: Error) => void;
close: (reason: string, description?: CloseDetails | Error) => void;
}
type SocketState = "opening" | "open" | "closing" | "closed";
interface WriteOptions {
compress?: boolean;
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes without upgrade mechanism, which means that it will keep the first low-level transport that
* successfully establishes the connection.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithoutUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithUpgrade
* @see Socket
*/
export declare class SocketWithoutUpgrade extends Emitter<Record<never, never>, Record<never, never>, SocketReservedEvents> {
id: string;
transport: Transport;
binaryType: BinaryType;
readyState: SocketState;
writeBuffer: Packet[];
protected readonly opts: BaseSocketOptions;
protected readonly transports: string[];
protected upgrading: boolean;
protected setTimeoutFn: typeof setTimeout;
private _prevBufferLen;
private _pingInterval;
private _pingTimeout;
private _maxPayload?;
private _pingTimeoutTimer;
/**
* The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
* callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
*/
private _pingTimeoutTime;
private clearTimeoutFn;
private readonly _beforeunloadEventListener;
private readonly _offlineEventListener;
private readonly secure;
private readonly hostname;
private readonly port;
private readonly _transportsByName;
/**
* The cookie jar will store the cookies sent by the server (Node. js only).
*/
readonly _cookieJar: CookieJar;
static priorWebsocketSuccess: boolean;
static protocol: number;
/**
* Socket constructor.
*
* @param {String|Object} uri - uri or options
* @param {Object} opts - options
*/
constructor(uri: string | BaseSocketOptions, opts: BaseSocketOptions);
/**
* Creates transport of the given type.
*
* @param {String} name - transport name
* @return {Transport}
* @private
*/
protected createTransport(name: string): Transport;
/**
* Initializes transport to use and starts probe.
*
* @private
*/
private _open;
/**
* Sets the current transport. Disables the existing one (if any).
*
* @private
*/
protected setTransport(transport: Transport): void;
/**
* Called when connection is deemed open.
*
* @private
*/
protected onOpen(): void;
/**
* Handles a packet.
*
* @private
*/
private _onPacket;
/**
* Called upon handshake completion.
*
* @param {Object} data - handshake obj
* @private
*/
protected onHandshake(data: HandshakeData): void;
/**
* Sets and resets ping timeout timer based on server pings.
*
* @private
*/
private _resetPingTimeout;
/**
* Called on `drain` event
*
* @private
*/
private _onDrain;
/**
* Flush write buffers.
*
* @private
*/
protected flush(): void;
/**
* Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
* long-polling)
*
* @private
*/
private _getWritablePackets;
/**
* Checks whether the heartbeat timer has expired but the socket has not yet been notified.
*
* Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
* `write()` method then the message would not be buffered by the Socket.IO client.
*
* @return {boolean}
* @private
*/
_hasPingExpired(): boolean;
/**
* Sends a message.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
write(msg: RawData, options?: WriteOptions, fn?: () => void): this;
/**
* Sends a message. Alias of {@link Socket#write}.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
send(msg: RawData, options?: WriteOptions, fn?: () => void): this;
/**
* Sends a packet.
*
* @param {String} type: packet type.
* @param {String} data.
* @param {Object} options.
* @param {Function} fn - callback function.
* @private
*/
private _sendPacket;
/**
* Closes the connection.
*/
close(): this;
/**
* Called upon transport error
*
* @private
*/
private _onError;
/**
* Called upon transport close.
*
* @private
*/
private _onClose;
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see Socket
*/
export declare class SocketWithUpgrade extends SocketWithoutUpgrade {
private _upgrades;
onOpen(): void;
/**
* Probes a transport.
*
* @param {String} name - transport name
* @private
*/
private _probe;
onHandshake(data: HandshakeData): void;
/**
* Filters upgrades, returning only those matching client transports.
*
* @param {Array} upgrades - server upgrades
* @private
*/
private _filterUpgrades;
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* @example
* import { Socket } from "engine.io-client";
*
* const socket = new Socket();
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see SocketWithUpgrade
*/
export declare class Socket extends SocketWithUpgrade {
constructor(uri?: string, opts?: SocketOptions);
constructor(opts: SocketOptions);
}
export {};

765
node_modules/engine.io-client/build/cjs/socket.js generated vendored Normal file
View File

@ -0,0 +1,765 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Socket = exports.SocketWithUpgrade = exports.SocketWithoutUpgrade = void 0;
const index_js_1 = require("./transports/index.js");
const util_js_1 = require("./util.js");
const parseqs_js_1 = require("./contrib/parseqs.js");
const parseuri_js_1 = require("./contrib/parseuri.js");
const component_emitter_1 = require("@socket.io/component-emitter");
const engine_io_parser_1 = require("engine.io-parser");
const globals_node_js_1 = require("./globals.node.js");
const debug_1 = __importDefault(require("debug")); // debug()
const debug = (0, debug_1.default)("engine.io-client:socket"); // debug()
const withEventListeners = typeof addEventListener === "function" &&
typeof removeEventListener === "function";
const OFFLINE_EVENT_LISTENERS = [];
if (withEventListeners) {
// within a ServiceWorker, any event handler for the 'offline' event must be added on the initial evaluation of the
// script, so we create one single event listener here which will forward the event to the socket instances
addEventListener("offline", () => {
debug("closing %d connection(s) because the network was lost", OFFLINE_EVENT_LISTENERS.length);
OFFLINE_EVENT_LISTENERS.forEach((listener) => listener());
}, false);
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes without upgrade mechanism, which means that it will keep the first low-level transport that
* successfully establishes the connection.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithoutUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithUpgrade
* @see Socket
*/
class SocketWithoutUpgrade extends component_emitter_1.Emitter {
/**
* Socket constructor.
*
* @param {String|Object} uri - uri or options
* @param {Object} opts - options
*/
constructor(uri, opts) {
super();
this.binaryType = globals_node_js_1.defaultBinaryType;
this.writeBuffer = [];
this._prevBufferLen = 0;
this._pingInterval = -1;
this._pingTimeout = -1;
this._maxPayload = -1;
/**
* The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
* callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
*/
this._pingTimeoutTime = Infinity;
if (uri && "object" === typeof uri) {
opts = uri;
uri = null;
}
if (uri) {
const parsedUri = (0, parseuri_js_1.parse)(uri);
opts.hostname = parsedUri.host;
opts.secure =
parsedUri.protocol === "https" || parsedUri.protocol === "wss";
opts.port = parsedUri.port;
if (parsedUri.query)
opts.query = parsedUri.query;
}
else if (opts.host) {
opts.hostname = (0, parseuri_js_1.parse)(opts.host).host;
}
(0, util_js_1.installTimerFunctions)(this, opts);
this.secure =
null != opts.secure
? opts.secure
: typeof location !== "undefined" && "https:" === location.protocol;
if (opts.hostname && !opts.port) {
// if no port is specified manually, use the protocol default
opts.port = this.secure ? "443" : "80";
}
this.hostname =
opts.hostname ||
(typeof location !== "undefined" ? location.hostname : "localhost");
this.port =
opts.port ||
(typeof location !== "undefined" && location.port
? location.port
: this.secure
? "443"
: "80");
this.transports = [];
this._transportsByName = {};
opts.transports.forEach((t) => {
const transportName = t.prototype.name;
this.transports.push(transportName);
this._transportsByName[transportName] = t;
});
this.opts = Object.assign({
path: "/engine.io",
agent: false,
withCredentials: false,
upgrade: true,
timestampParam: "t",
rememberUpgrade: false,
addTrailingSlash: true,
rejectUnauthorized: true,
perMessageDeflate: {
threshold: 1024,
},
transportOptions: {},
closeOnBeforeunload: false,
}, opts);
this.opts.path =
this.opts.path.replace(/\/$/, "") +
(this.opts.addTrailingSlash ? "/" : "");
if (typeof this.opts.query === "string") {
this.opts.query = (0, parseqs_js_1.decode)(this.opts.query);
}
if (withEventListeners) {
if (this.opts.closeOnBeforeunload) {
// Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
// ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
// closed/reloaded)
this._beforeunloadEventListener = () => {
if (this.transport) {
// silently close the transport
this.transport.removeAllListeners();
this.transport.close();
}
};
addEventListener("beforeunload", this._beforeunloadEventListener, false);
}
if (this.hostname !== "localhost") {
debug("adding listener for the 'offline' event");
this._offlineEventListener = () => {
this._onClose("transport close", {
description: "network connection lost",
});
};
OFFLINE_EVENT_LISTENERS.push(this._offlineEventListener);
}
}
if (this.opts.withCredentials) {
this._cookieJar = (0, globals_node_js_1.createCookieJar)();
}
this._open();
}
/**
* Creates transport of the given type.
*
* @param {String} name - transport name
* @return {Transport}
* @private
*/
createTransport(name) {
debug('creating transport "%s"', name);
const query = Object.assign({}, this.opts.query);
// append engine.io protocol identifier
query.EIO = engine_io_parser_1.protocol;
// transport name
query.transport = name;
// session id if we already have one
if (this.id)
query.sid = this.id;
const opts = Object.assign({}, this.opts, {
query,
socket: this,
hostname: this.hostname,
secure: this.secure,
port: this.port,
}, this.opts.transportOptions[name]);
debug("options: %j", opts);
return new this._transportsByName[name](opts);
}
/**
* Initializes transport to use and starts probe.
*
* @private
*/
_open() {
if (this.transports.length === 0) {
// Emit error on next tick so it can be listened to
this.setTimeoutFn(() => {
this.emitReserved("error", "No transports available");
}, 0);
return;
}
const transportName = this.opts.rememberUpgrade &&
SocketWithoutUpgrade.priorWebsocketSuccess &&
this.transports.indexOf("websocket") !== -1
? "websocket"
: this.transports[0];
this.readyState = "opening";
const transport = this.createTransport(transportName);
transport.open();
this.setTransport(transport);
}
/**
* Sets the current transport. Disables the existing one (if any).
*
* @private
*/
setTransport(transport) {
debug("setting transport %s", transport.name);
if (this.transport) {
debug("clearing existing transport %s", this.transport.name);
this.transport.removeAllListeners();
}
// set up transport
this.transport = transport;
// set up transport listeners
transport
.on("drain", this._onDrain.bind(this))
.on("packet", this._onPacket.bind(this))
.on("error", this._onError.bind(this))
.on("close", (reason) => this._onClose("transport close", reason));
}
/**
* Called when connection is deemed open.
*
* @private
*/
onOpen() {
debug("socket open");
this.readyState = "open";
SocketWithoutUpgrade.priorWebsocketSuccess =
"websocket" === this.transport.name;
this.emitReserved("open");
this.flush();
}
/**
* Handles a packet.
*
* @private
*/
_onPacket(packet) {
if ("opening" === this.readyState ||
"open" === this.readyState ||
"closing" === this.readyState) {
debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
this.emitReserved("packet", packet);
// Socket is live - any packet counts
this.emitReserved("heartbeat");
switch (packet.type) {
case "open":
this.onHandshake(JSON.parse(packet.data));
break;
case "ping":
this._sendPacket("pong");
this.emitReserved("ping");
this.emitReserved("pong");
this._resetPingTimeout();
break;
case "error":
const err = new Error("server error");
// @ts-ignore
err.code = packet.data;
this._onError(err);
break;
case "message":
this.emitReserved("data", packet.data);
this.emitReserved("message", packet.data);
break;
}
}
else {
debug('packet received with socket readyState "%s"', this.readyState);
}
}
/**
* Called upon handshake completion.
*
* @param {Object} data - handshake obj
* @private
*/
onHandshake(data) {
this.emitReserved("handshake", data);
this.id = data.sid;
this.transport.query.sid = data.sid;
this._pingInterval = data.pingInterval;
this._pingTimeout = data.pingTimeout;
this._maxPayload = data.maxPayload;
this.onOpen();
// In case open handler closes socket
if ("closed" === this.readyState)
return;
this._resetPingTimeout();
}
/**
* Sets and resets ping timeout timer based on server pings.
*
* @private
*/
_resetPingTimeout() {
this.clearTimeoutFn(this._pingTimeoutTimer);
const delay = this._pingInterval + this._pingTimeout;
this._pingTimeoutTime = Date.now() + delay;
this._pingTimeoutTimer = this.setTimeoutFn(() => {
this._onClose("ping timeout");
}, delay);
if (this.opts.autoUnref) {
this._pingTimeoutTimer.unref();
}
}
/**
* Called on `drain` event
*
* @private
*/
_onDrain() {
this.writeBuffer.splice(0, this._prevBufferLen);
// setting prevBufferLen = 0 is very important
// for example, when upgrading, upgrade packet is sent over,
// and a nonzero prevBufferLen could cause problems on `drain`
this._prevBufferLen = 0;
if (0 === this.writeBuffer.length) {
this.emitReserved("drain");
}
else {
this.flush();
}
}
/**
* Flush write buffers.
*
* @private
*/
flush() {
if ("closed" !== this.readyState &&
this.transport.writable &&
!this.upgrading &&
this.writeBuffer.length) {
const packets = this._getWritablePackets();
debug("flushing %d packets in socket", packets.length);
this.transport.send(packets);
// keep track of current length of writeBuffer
// splice writeBuffer and callbackBuffer on `drain`
this._prevBufferLen = packets.length;
this.emitReserved("flush");
}
}
/**
* Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
* long-polling)
*
* @private
*/
_getWritablePackets() {
const shouldCheckPayloadSize = this._maxPayload &&
this.transport.name === "polling" &&
this.writeBuffer.length > 1;
if (!shouldCheckPayloadSize) {
return this.writeBuffer;
}
let payloadSize = 1; // first packet type
for (let i = 0; i < this.writeBuffer.length; i++) {
const data = this.writeBuffer[i].data;
if (data) {
payloadSize += (0, util_js_1.byteLength)(data);
}
if (i > 0 && payloadSize > this._maxPayload) {
debug("only send %d out of %d packets", i, this.writeBuffer.length);
return this.writeBuffer.slice(0, i);
}
payloadSize += 2; // separator + packet type
}
debug("payload size is %d (max: %d)", payloadSize, this._maxPayload);
return this.writeBuffer;
}
/**
* Checks whether the heartbeat timer has expired but the socket has not yet been notified.
*
* Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
* `write()` method then the message would not be buffered by the Socket.IO client.
*
* @return {boolean}
* @private
*/
/* private */ _hasPingExpired() {
if (!this._pingTimeoutTime)
return true;
const hasExpired = Date.now() > this._pingTimeoutTime;
if (hasExpired) {
debug("throttled timer detected, scheduling connection close");
this._pingTimeoutTime = 0;
(0, globals_node_js_1.nextTick)(() => {
this._onClose("ping timeout");
}, this.setTimeoutFn);
}
return hasExpired;
}
/**
* Sends a message.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
write(msg, options, fn) {
this._sendPacket("message", msg, options, fn);
return this;
}
/**
* Sends a message. Alias of {@link Socket#write}.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
send(msg, options, fn) {
this._sendPacket("message", msg, options, fn);
return this;
}
/**
* Sends a packet.
*
* @param {String} type: packet type.
* @param {String} data.
* @param {Object} options.
* @param {Function} fn - callback function.
* @private
*/
_sendPacket(type, data, options, fn) {
if ("function" === typeof data) {
fn = data;
data = undefined;
}
if ("function" === typeof options) {
fn = options;
options = null;
}
if ("closing" === this.readyState || "closed" === this.readyState) {
return;
}
options = options || {};
options.compress = false !== options.compress;
const packet = {
type: type,
data: data,
options: options,
};
this.emitReserved("packetCreate", packet);
this.writeBuffer.push(packet);
if (fn)
this.once("flush", fn);
this.flush();
}
/**
* Closes the connection.
*/
close() {
const close = () => {
this._onClose("forced close");
debug("socket closing - telling transport to close");
this.transport.close();
};
const cleanupAndClose = () => {
this.off("upgrade", cleanupAndClose);
this.off("upgradeError", cleanupAndClose);
close();
};
const waitForUpgrade = () => {
// wait for upgrade to finish since we can't send packets while pausing a transport
this.once("upgrade", cleanupAndClose);
this.once("upgradeError", cleanupAndClose);
};
if ("opening" === this.readyState || "open" === this.readyState) {
this.readyState = "closing";
if (this.writeBuffer.length) {
this.once("drain", () => {
if (this.upgrading) {
waitForUpgrade();
}
else {
close();
}
});
}
else if (this.upgrading) {
waitForUpgrade();
}
else {
close();
}
}
return this;
}
/**
* Called upon transport error
*
* @private
*/
_onError(err) {
debug("socket error %j", err);
SocketWithoutUpgrade.priorWebsocketSuccess = false;
if (this.opts.tryAllTransports &&
this.transports.length > 1 &&
this.readyState === "opening") {
debug("trying next transport");
this.transports.shift();
return this._open();
}
this.emitReserved("error", err);
this._onClose("transport error", err);
}
/**
* Called upon transport close.
*
* @private
*/
_onClose(reason, description) {
if ("opening" === this.readyState ||
"open" === this.readyState ||
"closing" === this.readyState) {
debug('socket close with reason: "%s"', reason);
// clear timers
this.clearTimeoutFn(this._pingTimeoutTimer);
// stop event from firing again for transport
this.transport.removeAllListeners("close");
// ensure transport won't stay open
this.transport.close();
// ignore further transport communication
this.transport.removeAllListeners();
if (withEventListeners) {
if (this._beforeunloadEventListener) {
removeEventListener("beforeunload", this._beforeunloadEventListener, false);
}
if (this._offlineEventListener) {
const i = OFFLINE_EVENT_LISTENERS.indexOf(this._offlineEventListener);
if (i !== -1) {
debug("removing listener for the 'offline' event");
OFFLINE_EVENT_LISTENERS.splice(i, 1);
}
}
}
// set ready state
this.readyState = "closed";
// clear session id
this.id = null;
// emit close event
this.emitReserved("close", reason, description);
// clean buffers after, so users can still
// grab the buffers on `close` event
this.writeBuffer = [];
this._prevBufferLen = 0;
}
}
}
exports.SocketWithoutUpgrade = SocketWithoutUpgrade;
SocketWithoutUpgrade.protocol = engine_io_parser_1.protocol;
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see Socket
*/
class SocketWithUpgrade extends SocketWithoutUpgrade {
constructor() {
super(...arguments);
this._upgrades = [];
}
onOpen() {
super.onOpen();
if ("open" === this.readyState && this.opts.upgrade) {
debug("starting upgrade probes");
for (let i = 0; i < this._upgrades.length; i++) {
this._probe(this._upgrades[i]);
}
}
}
/**
* Probes a transport.
*
* @param {String} name - transport name
* @private
*/
_probe(name) {
debug('probing transport "%s"', name);
let transport = this.createTransport(name);
let failed = false;
SocketWithoutUpgrade.priorWebsocketSuccess = false;
const onTransportOpen = () => {
if (failed)
return;
debug('probe transport "%s" opened', name);
transport.send([{ type: "ping", data: "probe" }]);
transport.once("packet", (msg) => {
if (failed)
return;
if ("pong" === msg.type && "probe" === msg.data) {
debug('probe transport "%s" pong', name);
this.upgrading = true;
this.emitReserved("upgrading", transport);
if (!transport)
return;
SocketWithoutUpgrade.priorWebsocketSuccess =
"websocket" === transport.name;
debug('pausing current transport "%s"', this.transport.name);
this.transport.pause(() => {
if (failed)
return;
if ("closed" === this.readyState)
return;
debug("changing transport and sending upgrade packet");
cleanup();
this.setTransport(transport);
transport.send([{ type: "upgrade" }]);
this.emitReserved("upgrade", transport);
transport = null;
this.upgrading = false;
this.flush();
});
}
else {
debug('probe transport "%s" failed', name);
const err = new Error("probe error");
// @ts-ignore
err.transport = transport.name;
this.emitReserved("upgradeError", err);
}
});
};
function freezeTransport() {
if (failed)
return;
// Any callback called by transport should be ignored since now
failed = true;
cleanup();
transport.close();
transport = null;
}
// Handle any error that happens while probing
const onerror = (err) => {
const error = new Error("probe error: " + err);
// @ts-ignore
error.transport = transport.name;
freezeTransport();
debug('probe transport "%s" failed because of error: %s', name, err);
this.emitReserved("upgradeError", error);
};
function onTransportClose() {
onerror("transport closed");
}
// When the socket is closed while we're probing
function onclose() {
onerror("socket closed");
}
// When the socket is upgraded while we're probing
function onupgrade(to) {
if (transport && to.name !== transport.name) {
debug('"%s" works - aborting "%s"', to.name, transport.name);
freezeTransport();
}
}
// Remove all listeners on the transport and on self
const cleanup = () => {
transport.removeListener("open", onTransportOpen);
transport.removeListener("error", onerror);
transport.removeListener("close", onTransportClose);
this.off("close", onclose);
this.off("upgrading", onupgrade);
};
transport.once("open", onTransportOpen);
transport.once("error", onerror);
transport.once("close", onTransportClose);
this.once("close", onclose);
this.once("upgrading", onupgrade);
if (this._upgrades.indexOf("webtransport") !== -1 &&
name !== "webtransport") {
// favor WebTransport
this.setTimeoutFn(() => {
if (!failed) {
transport.open();
}
}, 200);
}
else {
transport.open();
}
}
onHandshake(data) {
this._upgrades = this._filterUpgrades(data.upgrades);
super.onHandshake(data);
}
/**
* Filters upgrades, returning only those matching client transports.
*
* @param {Array} upgrades - server upgrades
* @private
*/
_filterUpgrades(upgrades) {
const filteredUpgrades = [];
for (let i = 0; i < upgrades.length; i++) {
if (~this.transports.indexOf(upgrades[i]))
filteredUpgrades.push(upgrades[i]);
}
return filteredUpgrades;
}
}
exports.SocketWithUpgrade = SocketWithUpgrade;
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* @example
* import { Socket } from "engine.io-client";
*
* const socket = new Socket();
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see SocketWithUpgrade
*/
class Socket extends SocketWithUpgrade {
constructor(uri, opts = {}) {
const o = typeof uri === "object" ? uri : opts;
if (!o.transports ||
(o.transports && typeof o.transports[0] === "string")) {
o.transports = (o.transports || ["polling", "websocket", "webtransport"])
.map((transportName) => index_js_1.transports[transportName])
.filter((t) => !!t);
}
super(uri, o);
}
}
exports.Socket = Socket;

106
node_modules/engine.io-client/build/cjs/transport.d.ts generated vendored Normal file
View File

@ -0,0 +1,106 @@
import type { Packet, RawData } from "engine.io-parser";
import { Emitter } from "@socket.io/component-emitter";
import type { Socket, SocketOptions } from "./socket.js";
export declare class TransportError extends Error {
readonly description: any;
readonly context: any;
readonly type = "TransportError";
constructor(reason: string, description: any, context: any);
}
export interface CloseDetails {
description: string;
context?: unknown;
}
interface TransportReservedEvents {
open: () => void;
error: (err: TransportError) => void;
packet: (packet: Packet) => void;
close: (details?: CloseDetails) => void;
poll: () => void;
pollComplete: () => void;
drain: () => void;
}
type TransportState = "opening" | "open" | "closed" | "pausing" | "paused";
export declare abstract class Transport extends Emitter<Record<never, never>, Record<never, never>, TransportReservedEvents> {
query: Record<string, string>;
writable: boolean;
protected opts: SocketOptions;
protected supportsBinary: boolean;
protected readyState: TransportState;
protected socket: Socket;
protected setTimeoutFn: typeof setTimeout;
/**
* Transport abstract constructor.
*
* @param {Object} opts - options
* @protected
*/
constructor(opts: any);
/**
* Emits an error.
*
* @param {String} reason
* @param description
* @param context - the error context
* @return {Transport} for chaining
* @protected
*/
protected onError(reason: string, description: any, context?: any): this;
/**
* Opens the transport.
*/
open(): this;
/**
* Closes the transport.
*/
close(): this;
/**
* Sends multiple packets.
*
* @param {Array} packets
*/
send(packets: any): void;
/**
* Called upon open
*
* @protected
*/
protected onOpen(): void;
/**
* Called with data.
*
* @param {String} data
* @protected
*/
protected onData(data: RawData): void;
/**
* Called with a decoded packet.
*
* @protected
*/
protected onPacket(packet: Packet): void;
/**
* Called upon close.
*
* @protected
*/
protected onClose(details?: CloseDetails): void;
/**
* The name of the transport
*/
abstract get name(): string;
/**
* Pauses the transport, in order not to lose packets during an upgrade.
*
* @param onPause
*/
pause(onPause: () => void): void;
protected createUri(schema: string, query?: Record<string, unknown>): string;
private _hostname;
private _port;
private _query;
protected abstract doOpen(): any;
protected abstract doClose(): any;
protected abstract write(packets: Packet[]): any;
}
export {};

153
node_modules/engine.io-client/build/cjs/transport.js generated vendored Normal file
View File

@ -0,0 +1,153 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transport = exports.TransportError = void 0;
const engine_io_parser_1 = require("engine.io-parser");
const component_emitter_1 = require("@socket.io/component-emitter");
const util_js_1 = require("./util.js");
const parseqs_js_1 = require("./contrib/parseqs.js");
const debug_1 = __importDefault(require("debug")); // debug()
const debug = (0, debug_1.default)("engine.io-client:transport"); // debug()
class TransportError extends Error {
constructor(reason, description, context) {
super(reason);
this.description = description;
this.context = context;
this.type = "TransportError";
}
}
exports.TransportError = TransportError;
class Transport extends component_emitter_1.Emitter {
/**
* Transport abstract constructor.
*
* @param {Object} opts - options
* @protected
*/
constructor(opts) {
super();
this.writable = false;
(0, util_js_1.installTimerFunctions)(this, opts);
this.opts = opts;
this.query = opts.query;
this.socket = opts.socket;
this.supportsBinary = !opts.forceBase64;
}
/**
* Emits an error.
*
* @param {String} reason
* @param description
* @param context - the error context
* @return {Transport} for chaining
* @protected
*/
onError(reason, description, context) {
super.emitReserved("error", new TransportError(reason, description, context));
return this;
}
/**
* Opens the transport.
*/
open() {
this.readyState = "opening";
this.doOpen();
return this;
}
/**
* Closes the transport.
*/
close() {
if (this.readyState === "opening" || this.readyState === "open") {
this.doClose();
this.onClose();
}
return this;
}
/**
* Sends multiple packets.
*
* @param {Array} packets
*/
send(packets) {
if (this.readyState === "open") {
this.write(packets);
}
else {
// this might happen if the transport was silently closed in the beforeunload event handler
debug("transport is not open, discarding packets");
}
}
/**
* Called upon open
*
* @protected
*/
onOpen() {
this.readyState = "open";
this.writable = true;
super.emitReserved("open");
}
/**
* Called with data.
*
* @param {String} data
* @protected
*/
onData(data) {
const packet = (0, engine_io_parser_1.decodePacket)(data, this.socket.binaryType);
this.onPacket(packet);
}
/**
* Called with a decoded packet.
*
* @protected
*/
onPacket(packet) {
super.emitReserved("packet", packet);
}
/**
* Called upon close.
*
* @protected
*/
onClose(details) {
this.readyState = "closed";
super.emitReserved("close", details);
}
/**
* Pauses the transport, in order not to lose packets during an upgrade.
*
* @param onPause
*/
pause(onPause) { }
createUri(schema, query = {}) {
return (schema +
"://" +
this._hostname() +
this._port() +
this.opts.path +
this._query(query));
}
_hostname() {
const hostname = this.opts.hostname;
return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
}
_port() {
if (this.opts.port &&
((this.opts.secure && Number(this.opts.port !== 443)) ||
(!this.opts.secure && Number(this.opts.port) !== 80))) {
return ":" + this.opts.port;
}
else {
return "";
}
}
_query(query) {
const encodedQuery = (0, parseqs_js_1.encode)(query);
return encodedQuery.length ? "?" + encodedQuery : "";
}
}
exports.Transport = Transport;

View File

@ -0,0 +1,8 @@
import { XHR } from "./polling-xhr.node.js";
import { WS } from "./websocket.node.js";
import { WT } from "./webtransport.js";
export declare const transports: {
websocket: typeof WS;
webtransport: typeof WT;
polling: typeof XHR;
};

View File

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.transports = void 0;
const polling_xhr_node_js_1 = require("./polling-xhr.node.js");
const websocket_node_js_1 = require("./websocket.node.js");
const webtransport_js_1 = require("./webtransport.js");
exports.transports = {
websocket: websocket_node_js_1.WS,
webtransport: webtransport_js_1.WT,
polling: polling_xhr_node_js_1.XHR,
};

View File

@ -0,0 +1,15 @@
import { Polling } from "./polling.js";
/**
* HTTP long-polling based on the built-in `fetch()` method.
*
* Usage: browser, Node.js (since v18), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/fetch
* @see https://caniuse.com/fetch
* @see https://nodejs.org/api/globals.html#fetch
*/
export declare class Fetch extends Polling {
doPoll(): void;
doWrite(data: string, callback: () => void): void;
private _fetch;
}

View File

@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Fetch = void 0;
const polling_js_1 = require("./polling.js");
/**
* HTTP long-polling based on the built-in `fetch()` method.
*
* Usage: browser, Node.js (since v18), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/fetch
* @see https://caniuse.com/fetch
* @see https://nodejs.org/api/globals.html#fetch
*/
class Fetch extends polling_js_1.Polling {
doPoll() {
this._fetch()
.then((res) => {
if (!res.ok) {
return this.onError("fetch read error", res.status, res);
}
res.text().then((data) => this.onData(data));
})
.catch((err) => {
this.onError("fetch read error", err);
});
}
doWrite(data, callback) {
this._fetch(data)
.then((res) => {
if (!res.ok) {
return this.onError("fetch write error", res.status, res);
}
callback();
})
.catch((err) => {
this.onError("fetch write error", err);
});
}
_fetch(data) {
var _a;
const isPost = data !== undefined;
const headers = new Headers(this.opts.extraHeaders);
if (isPost) {
headers.set("content-type", "text/plain;charset=UTF-8");
}
(_a = this.socket._cookieJar) === null || _a === void 0 ? void 0 : _a.appendCookies(headers);
return fetch(this.uri(), {
method: isPost ? "POST" : "GET",
body: isPost ? data : null,
headers,
credentials: this.opts.withCredentials ? "include" : "omit",
}).then((res) => {
var _a;
// @ts-ignore getSetCookie() was added in Node.js v19.7.0
(_a = this.socket._cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(res.headers.getSetCookie());
return res;
});
}
}
exports.Fetch = Fetch;

View File

@ -0,0 +1,108 @@
import { Polling } from "./polling.js";
import { Emitter } from "@socket.io/component-emitter";
import type { SocketOptions } from "../socket.js";
import type { CookieJar } from "../globals.node.js";
import type { RawData } from "engine.io-parser";
export declare abstract class BaseXHR extends Polling {
protected readonly xd: boolean;
private pollXhr;
/**
* XHR Polling constructor.
*
* @param {Object} opts
* @package
*/
constructor(opts: any);
/**
* Creates a request.
*
* @private
*/
abstract request(opts?: Record<string, any>): any;
/**
* Sends data.
*
* @param {String} data to send.
* @param {Function} called upon flush.
* @private
*/
doWrite(data: any, fn: any): void;
/**
* Starts a poll cycle.
*
* @private
*/
doPoll(): void;
}
interface RequestReservedEvents {
success: () => void;
data: (data: RawData) => void;
error: (err: number | Error, context: unknown) => void;
}
export type RequestOptions = SocketOptions & {
method?: string;
data?: RawData;
xd: boolean;
cookieJar: CookieJar;
};
export declare class Request extends Emitter<Record<never, never>, Record<never, never>, RequestReservedEvents> {
private readonly createRequest;
private readonly _opts;
private readonly _method;
private readonly _uri;
private readonly _data;
private _xhr;
private setTimeoutFn;
private _index;
static requestsCount: number;
static requests: {};
/**
* Request constructor
*
* @param {Object} options
* @package
*/
constructor(createRequest: (opts: RequestOptions) => XMLHttpRequest, uri: string, opts: RequestOptions);
/**
* Creates the XHR object and sends the request.
*
* @private
*/
private _create;
/**
* Called upon error.
*
* @private
*/
private _onError;
/**
* Cleans up house.
*
* @private
*/
private _cleanup;
/**
* Called upon load.
*
* @private
*/
private _onLoad;
/**
* Aborts the request.
*
* @package
*/
abort(): void;
}
/**
* HTTP long-polling based on the built-in `XMLHttpRequest` object.
*
* Usage: browser
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
export declare class XHR extends BaseXHR {
constructor(opts: any);
request(opts?: Record<string, any>): Request;
}
export {};

View File

@ -0,0 +1,285 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XHR = exports.Request = exports.BaseXHR = void 0;
const polling_js_1 = require("./polling.js");
const component_emitter_1 = require("@socket.io/component-emitter");
const util_js_1 = require("../util.js");
const globals_node_js_1 = require("../globals.node.js");
const has_cors_js_1 = require("../contrib/has-cors.js");
const debug_1 = __importDefault(require("debug")); // debug()
const debug = (0, debug_1.default)("engine.io-client:polling"); // debug()
function empty() { }
class BaseXHR extends polling_js_1.Polling {
/**
* XHR Polling constructor.
*
* @param {Object} opts
* @package
*/
constructor(opts) {
super(opts);
if (typeof location !== "undefined") {
const isSSL = "https:" === location.protocol;
let port = location.port;
// some user agents have empty `location.port`
if (!port) {
port = isSSL ? "443" : "80";
}
this.xd =
(typeof location !== "undefined" &&
opts.hostname !== location.hostname) ||
port !== opts.port;
}
}
/**
* Sends data.
*
* @param {String} data to send.
* @param {Function} called upon flush.
* @private
*/
doWrite(data, fn) {
const req = this.request({
method: "POST",
data: data,
});
req.on("success", fn);
req.on("error", (xhrStatus, context) => {
this.onError("xhr post error", xhrStatus, context);
});
}
/**
* Starts a poll cycle.
*
* @private
*/
doPoll() {
debug("xhr poll");
const req = this.request();
req.on("data", this.onData.bind(this));
req.on("error", (xhrStatus, context) => {
this.onError("xhr poll error", xhrStatus, context);
});
this.pollXhr = req;
}
}
exports.BaseXHR = BaseXHR;
class Request extends component_emitter_1.Emitter {
/**
* Request constructor
*
* @param {Object} options
* @package
*/
constructor(createRequest, uri, opts) {
super();
this.createRequest = createRequest;
(0, util_js_1.installTimerFunctions)(this, opts);
this._opts = opts;
this._method = opts.method || "GET";
this._uri = uri;
this._data = undefined !== opts.data ? opts.data : null;
this._create();
}
/**
* Creates the XHR object and sends the request.
*
* @private
*/
_create() {
var _a;
const opts = (0, util_js_1.pick)(this._opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
opts.xdomain = !!this._opts.xd;
const xhr = (this._xhr = this.createRequest(opts));
try {
debug("xhr open %s: %s", this._method, this._uri);
xhr.open(this._method, this._uri, true);
try {
if (this._opts.extraHeaders) {
// @ts-ignore
xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
for (let i in this._opts.extraHeaders) {
if (this._opts.extraHeaders.hasOwnProperty(i)) {
xhr.setRequestHeader(i, this._opts.extraHeaders[i]);
}
}
}
}
catch (e) { }
if ("POST" === this._method) {
try {
xhr.setRequestHeader("Content-type", "text/plain;charset=UTF-8");
}
catch (e) { }
}
try {
xhr.setRequestHeader("Accept", "*/*");
}
catch (e) { }
(_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
// ie6 check
if ("withCredentials" in xhr) {
xhr.withCredentials = this._opts.withCredentials;
}
if (this._opts.requestTimeout) {
xhr.timeout = this._opts.requestTimeout;
}
xhr.onreadystatechange = () => {
var _a;
if (xhr.readyState === 3) {
(_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(
// @ts-ignore
xhr.getResponseHeader("set-cookie"));
}
if (4 !== xhr.readyState)
return;
if (200 === xhr.status || 1223 === xhr.status) {
this._onLoad();
}
else {
// make sure the `error` event handler that's user-set
// does not throw in the same tick and gets caught here
this.setTimeoutFn(() => {
this._onError(typeof xhr.status === "number" ? xhr.status : 0);
}, 0);
}
};
debug("xhr data %s", this._data);
xhr.send(this._data);
}
catch (e) {
// Need to defer since .create() is called directly from the constructor
// and thus the 'error' event can only be only bound *after* this exception
// occurs. Therefore, also, we cannot throw here at all.
this.setTimeoutFn(() => {
this._onError(e);
}, 0);
return;
}
if (typeof document !== "undefined") {
this._index = Request.requestsCount++;
Request.requests[this._index] = this;
}
}
/**
* Called upon error.
*
* @private
*/
_onError(err) {
this.emitReserved("error", err, this._xhr);
this._cleanup(true);
}
/**
* Cleans up house.
*
* @private
*/
_cleanup(fromError) {
if ("undefined" === typeof this._xhr || null === this._xhr) {
return;
}
this._xhr.onreadystatechange = empty;
if (fromError) {
try {
this._xhr.abort();
}
catch (e) { }
}
if (typeof document !== "undefined") {
delete Request.requests[this._index];
}
this._xhr = null;
}
/**
* Called upon load.
*
* @private
*/
_onLoad() {
const data = this._xhr.responseText;
if (data !== null) {
this.emitReserved("data", data);
this.emitReserved("success");
this._cleanup();
}
}
/**
* Aborts the request.
*
* @package
*/
abort() {
this._cleanup();
}
}
exports.Request = Request;
Request.requestsCount = 0;
Request.requests = {};
/**
* Aborts pending requests when unloading the window. This is needed to prevent
* memory leaks (e.g. when using IE) and to ensure that no spurious error is
* emitted.
*/
if (typeof document !== "undefined") {
// @ts-ignore
if (typeof attachEvent === "function") {
// @ts-ignore
attachEvent("onunload", unloadHandler);
}
else if (typeof addEventListener === "function") {
const terminationEvent = "onpagehide" in globals_node_js_1.globalThisShim ? "pagehide" : "unload";
addEventListener(terminationEvent, unloadHandler, false);
}
}
function unloadHandler() {
for (let i in Request.requests) {
if (Request.requests.hasOwnProperty(i)) {
Request.requests[i].abort();
}
}
}
const hasXHR2 = (function () {
const xhr = newRequest({
xdomain: false,
});
return xhr && xhr.responseType !== null;
})();
/**
* HTTP long-polling based on the built-in `XMLHttpRequest` object.
*
* Usage: browser
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
class XHR extends BaseXHR {
constructor(opts) {
super(opts);
const forceBase64 = opts && opts.forceBase64;
this.supportsBinary = hasXHR2 && !forceBase64;
}
request(opts = {}) {
Object.assign(opts, { xd: this.xd }, this.opts);
return new Request(newRequest, this.uri(), opts);
}
}
exports.XHR = XHR;
function newRequest(opts) {
const xdomain = opts.xdomain;
// XMLHttpRequest can be disabled on IE
try {
if ("undefined" !== typeof XMLHttpRequest && (!xdomain || has_cors_js_1.hasCORS)) {
return new XMLHttpRequest();
}
}
catch (e) { }
if (!xdomain) {
try {
return new globals_node_js_1.globalThisShim[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
}
catch (e) { }
}
}

View File

@ -0,0 +1,11 @@
import { BaseXHR, Request } from "./polling-xhr.js";
/**
* HTTP long-polling based on the `XMLHttpRequest` object provided by the `xmlhttprequest-ssl` package.
*
* Usage: Node.js, Deno (compat), Bun (compat)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
export declare class XHR extends BaseXHR {
request(opts?: Record<string, any>): Request;
}

View File

@ -0,0 +1,44 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XHR = void 0;
const XMLHttpRequestModule = __importStar(require("xmlhttprequest-ssl"));
const polling_xhr_js_1 = require("./polling-xhr.js");
const XMLHttpRequest = XMLHttpRequestModule.default || XMLHttpRequestModule;
/**
* HTTP long-polling based on the `XMLHttpRequest` object provided by the `xmlhttprequest-ssl` package.
*
* Usage: Node.js, Deno (compat), Bun (compat)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
class XHR extends polling_xhr_js_1.BaseXHR {
request(opts = {}) {
var _a;
Object.assign(opts, { xd: this.xd, cookieJar: (_a = this.socket) === null || _a === void 0 ? void 0 : _a._cookieJar }, this.opts);
return new polling_xhr_js_1.Request((opts) => new XMLHttpRequest(opts), this.uri(), opts);
}
}
exports.XHR = XHR;

View File

@ -0,0 +1,52 @@
import { Transport } from "../transport.js";
export declare abstract class Polling extends Transport {
private _polling;
get name(): string;
/**
* Opens the socket (triggers polling). We write a PING message to determine
* when the transport is open.
*
* @protected
*/
doOpen(): void;
/**
* Pauses polling.
*
* @param {Function} onPause - callback upon buffers are flushed and transport is paused
* @package
*/
pause(onPause: any): void;
/**
* Starts polling cycle.
*
* @private
*/
private _poll;
/**
* Overloads onData to detect payloads.
*
* @protected
*/
onData(data: any): void;
/**
* For polling, send a close packet.
*
* @protected
*/
doClose(): void;
/**
* Writes a packets payload.
*
* @param {Array} packets - data packets
* @protected
*/
write(packets: any): void;
/**
* Generates uri for connection.
*
* @private
*/
protected uri(): string;
abstract doPoll(): any;
abstract doWrite(data: string, callback: () => void): any;
}

View File

@ -0,0 +1,165 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Polling = void 0;
const transport_js_1 = require("../transport.js");
const util_js_1 = require("../util.js");
const engine_io_parser_1 = require("engine.io-parser");
const debug_1 = __importDefault(require("debug")); // debug()
const debug = (0, debug_1.default)("engine.io-client:polling"); // debug()
class Polling extends transport_js_1.Transport {
constructor() {
super(...arguments);
this._polling = false;
}
get name() {
return "polling";
}
/**
* Opens the socket (triggers polling). We write a PING message to determine
* when the transport is open.
*
* @protected
*/
doOpen() {
this._poll();
}
/**
* Pauses polling.
*
* @param {Function} onPause - callback upon buffers are flushed and transport is paused
* @package
*/
pause(onPause) {
this.readyState = "pausing";
const pause = () => {
debug("paused");
this.readyState = "paused";
onPause();
};
if (this._polling || !this.writable) {
let total = 0;
if (this._polling) {
debug("we are currently polling - waiting to pause");
total++;
this.once("pollComplete", function () {
debug("pre-pause polling complete");
--total || pause();
});
}
if (!this.writable) {
debug("we are currently writing - waiting to pause");
total++;
this.once("drain", function () {
debug("pre-pause writing complete");
--total || pause();
});
}
}
else {
pause();
}
}
/**
* Starts polling cycle.
*
* @private
*/
_poll() {
debug("polling");
this._polling = true;
this.doPoll();
this.emitReserved("poll");
}
/**
* Overloads onData to detect payloads.
*
* @protected
*/
onData(data) {
debug("polling got data %s", data);
const callback = (packet) => {
// if its the first message we consider the transport open
if ("opening" === this.readyState && packet.type === "open") {
this.onOpen();
}
// if its a close packet, we close the ongoing requests
if ("close" === packet.type) {
this.onClose({ description: "transport closed by the server" });
return false;
}
// otherwise bypass onData and handle the message
this.onPacket(packet);
};
// decode payload
(0, engine_io_parser_1.decodePayload)(data, this.socket.binaryType).forEach(callback);
// if an event did not trigger closing
if ("closed" !== this.readyState) {
// if we got data we're not polling
this._polling = false;
this.emitReserved("pollComplete");
if ("open" === this.readyState) {
this._poll();
}
else {
debug('ignoring poll - transport state "%s"', this.readyState);
}
}
}
/**
* For polling, send a close packet.
*
* @protected
*/
doClose() {
const close = () => {
debug("writing close packet");
this.write([{ type: "close" }]);
};
if ("open" === this.readyState) {
debug("transport open - closing");
close();
}
else {
// in case we're trying to close while
// handshaking is in progress (GH-164)
debug("transport not open - deferring close");
this.once("open", close);
}
}
/**
* Writes a packets payload.
*
* @param {Array} packets - data packets
* @protected
*/
write(packets) {
this.writable = false;
(0, engine_io_parser_1.encodePayload)(packets, (data) => {
this.doWrite(data, () => {
this.writable = true;
this.emitReserved("drain");
});
});
}
/**
* Generates uri for connection.
*
* @private
*/
uri() {
const schema = this.opts.secure ? "https" : "http";
const query = this.query || {};
// cache busting is forced
if (false !== this.opts.timestampRequests) {
query[this.opts.timestampParam] = (0, util_js_1.randomString)();
}
if (!this.supportsBinary && !query.sid) {
query.b64 = 1;
}
return this.createUri(schema, query);
}
}
exports.Polling = Polling;

View File

@ -0,0 +1,36 @@
import { Transport } from "../transport.js";
import type { Packet, RawData } from "engine.io-parser";
export declare abstract class BaseWS extends Transport {
protected ws: any;
get name(): string;
doOpen(): this;
abstract createSocket(uri: string, protocols: string | string[] | undefined, opts: Record<string, any>): any;
/**
* Adds event listeners to the socket
*
* @private
*/
private addEventListeners;
write(packets: any): void;
abstract doWrite(packet: Packet, data: RawData): any;
doClose(): void;
/**
* Generates uri for connection.
*
* @private
*/
private uri;
}
/**
* WebSocket transport based on the built-in `WebSocket` object.
*
* Usage: browser, Node.js (since v21), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* @see https://caniuse.com/mdn-api_websocket
* @see https://nodejs.org/api/globals.html#websocket
*/
export declare class WS extends BaseWS {
createSocket(uri: string, protocols: string | string[] | undefined, opts: Record<string, any>): any;
doWrite(_packet: Packet, data: RawData): void;
}

View File

@ -0,0 +1,136 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WS = exports.BaseWS = void 0;
const transport_js_1 = require("../transport.js");
const util_js_1 = require("../util.js");
const engine_io_parser_1 = require("engine.io-parser");
const globals_node_js_1 = require("../globals.node.js");
const debug_1 = __importDefault(require("debug")); // debug()
const debug = (0, debug_1.default)("engine.io-client:websocket"); // debug()
// detect ReactNative environment
const isReactNative = typeof navigator !== "undefined" &&
typeof navigator.product === "string" &&
navigator.product.toLowerCase() === "reactnative";
class BaseWS extends transport_js_1.Transport {
get name() {
return "websocket";
}
doOpen() {
const uri = this.uri();
const protocols = this.opts.protocols;
// React Native only supports the 'headers' option, and will print a warning if anything else is passed
const opts = isReactNative
? {}
: (0, util_js_1.pick)(this.opts, "agent", "perMessageDeflate", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "localAddress", "protocolVersion", "origin", "maxPayload", "family", "checkServerIdentity");
if (this.opts.extraHeaders) {
opts.headers = this.opts.extraHeaders;
}
try {
this.ws = this.createSocket(uri, protocols, opts);
}
catch (err) {
return this.emitReserved("error", err);
}
this.ws.binaryType = this.socket.binaryType;
this.addEventListeners();
}
/**
* Adds event listeners to the socket
*
* @private
*/
addEventListeners() {
this.ws.onopen = () => {
if (this.opts.autoUnref) {
this.ws._socket.unref();
}
this.onOpen();
};
this.ws.onclose = (closeEvent) => this.onClose({
description: "websocket connection closed",
context: closeEvent,
});
this.ws.onmessage = (ev) => this.onData(ev.data);
this.ws.onerror = (e) => this.onError("websocket error", e);
}
write(packets) {
this.writable = false;
// encodePacket efficient as it uses WS framing
// no need for encodePayload
for (let i = 0; i < packets.length; i++) {
const packet = packets[i];
const lastPacket = i === packets.length - 1;
(0, engine_io_parser_1.encodePacket)(packet, this.supportsBinary, (data) => {
// Sometimes the websocket has already been closed but the browser didn't
// have a chance of informing us about it yet, in that case send will
// throw an error
try {
this.doWrite(packet, data);
}
catch (e) {
debug("websocket closed before onclose event");
}
if (lastPacket) {
// fake drain
// defer to next tick to allow Socket to clear writeBuffer
(0, globals_node_js_1.nextTick)(() => {
this.writable = true;
this.emitReserved("drain");
}, this.setTimeoutFn);
}
});
}
}
doClose() {
if (typeof this.ws !== "undefined") {
this.ws.onerror = () => { };
this.ws.close();
this.ws = null;
}
}
/**
* Generates uri for connection.
*
* @private
*/
uri() {
const schema = this.opts.secure ? "wss" : "ws";
const query = this.query || {};
// append timestamp to URI
if (this.opts.timestampRequests) {
query[this.opts.timestampParam] = (0, util_js_1.randomString)();
}
// communicate binary support capabilities
if (!this.supportsBinary) {
query.b64 = 1;
}
return this.createUri(schema, query);
}
}
exports.BaseWS = BaseWS;
const WebSocketCtor = globals_node_js_1.globalThisShim.WebSocket || globals_node_js_1.globalThisShim.MozWebSocket;
/**
* WebSocket transport based on the built-in `WebSocket` object.
*
* Usage: browser, Node.js (since v21), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* @see https://caniuse.com/mdn-api_websocket
* @see https://nodejs.org/api/globals.html#websocket
*/
class WS extends BaseWS {
createSocket(uri, protocols, opts) {
return !isReactNative
? protocols
? new WebSocketCtor(uri, protocols)
: new WebSocketCtor(uri)
: new WebSocketCtor(uri, protocols, opts);
}
doWrite(_packet, data) {
this.ws.send(data);
}
}
exports.WS = WS;

View File

@ -0,0 +1,14 @@
import type { Packet, RawData } from "engine.io-parser";
import { BaseWS } from "./websocket.js";
/**
* WebSocket transport based on the `WebSocket` object provided by the `ws` package.
*
* Usage: Node.js, Deno (compat), Bun (compat)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* @see https://caniuse.com/mdn-api_websocket
*/
export declare class WS extends BaseWS {
createSocket(uri: string, protocols: string | string[] | undefined, opts: Record<string, any>): any;
doWrite(packet: Packet, data: RawData): void;
}

View File

@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WS = void 0;
const ws_1 = require("ws");
const websocket_js_1 = require("./websocket.js");
/**
* WebSocket transport based on the `WebSocket` object provided by the `ws` package.
*
* Usage: Node.js, Deno (compat), Bun (compat)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* @see https://caniuse.com/mdn-api_websocket
*/
class WS extends websocket_js_1.BaseWS {
createSocket(uri, protocols, opts) {
var _a;
if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a._cookieJar) {
opts.headers = opts.headers || {};
opts.headers.cookie =
typeof opts.headers.cookie === "string"
? [opts.headers.cookie]
: opts.headers.cookie || [];
for (const [name, cookie] of this.socket._cookieJar.cookies) {
opts.headers.cookie.push(`${name}=${cookie.value}`);
}
}
return new ws_1.WebSocket(uri, protocols, opts);
}
doWrite(packet, data) {
const opts = {};
if (packet.options) {
opts.compress = packet.options.compress;
}
if (this.opts.perMessageDeflate) {
const len =
// @ts-ignore
"string" === typeof data ? Buffer.byteLength(data) : data.length;
if (len < this.opts.perMessageDeflate.threshold) {
opts.compress = false;
}
}
this.ws.send(data, opts);
}
}
exports.WS = WS;

View File

@ -0,0 +1,18 @@
import { Transport } from "../transport.js";
import { Packet } from "engine.io-parser";
/**
* WebTransport transport based on the built-in `WebTransport` object.
*
* Usage: browser, Node.js (with the `@fails-components/webtransport` package)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport
* @see https://caniuse.com/webtransport
*/
export declare class WT extends Transport {
private _transport;
private _writer;
get name(): string;
protected doOpen(): this;
protected write(packets: Packet[]): void;
protected doClose(): void;
}

View File

@ -0,0 +1,94 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WT = void 0;
const transport_js_1 = require("../transport.js");
const globals_node_js_1 = require("../globals.node.js");
const engine_io_parser_1 = require("engine.io-parser");
const debug_1 = __importDefault(require("debug")); // debug()
const debug = (0, debug_1.default)("engine.io-client:webtransport"); // debug()
/**
* WebTransport transport based on the built-in `WebTransport` object.
*
* Usage: browser, Node.js (with the `@fails-components/webtransport` package)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport
* @see https://caniuse.com/webtransport
*/
class WT extends transport_js_1.Transport {
get name() {
return "webtransport";
}
doOpen() {
try {
// @ts-ignore
this._transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
}
catch (err) {
return this.emitReserved("error", err);
}
this._transport.closed
.then(() => {
debug("transport closed gracefully");
this.onClose();
})
.catch((err) => {
debug("transport closed due to %s", err);
this.onError("webtransport error", err);
});
// note: we could have used async/await, but that would require some additional polyfills
this._transport.ready.then(() => {
this._transport.createBidirectionalStream().then((stream) => {
const decoderStream = (0, engine_io_parser_1.createPacketDecoderStream)(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
const reader = stream.readable.pipeThrough(decoderStream).getReader();
const encoderStream = (0, engine_io_parser_1.createPacketEncoderStream)();
encoderStream.readable.pipeTo(stream.writable);
this._writer = encoderStream.writable.getWriter();
const read = () => {
reader
.read()
.then(({ done, value }) => {
if (done) {
debug("session is closed");
return;
}
debug("received chunk: %o", value);
this.onPacket(value);
read();
})
.catch((err) => {
debug("an error occurred while reading: %s", err);
});
};
read();
const packet = { type: "open" };
if (this.query.sid) {
packet.data = `{"sid":"${this.query.sid}"}`;
}
this._writer.write(packet).then(() => this.onOpen());
});
});
}
write(packets) {
this.writable = false;
for (let i = 0; i < packets.length; i++) {
const packet = packets[i];
const lastPacket = i === packets.length - 1;
this._writer.write(packet).then(() => {
if (lastPacket) {
(0, globals_node_js_1.nextTick)(() => {
this.writable = true;
this.emitReserved("drain");
}, this.setTimeoutFn);
}
});
}
}
doClose() {
var _a;
(_a = this._transport) === null || _a === void 0 ? void 0 : _a.close();
}
}
exports.WT = WT;

7
node_modules/engine.io-client/build/cjs/util.d.ts generated vendored Normal file
View File

@ -0,0 +1,7 @@
export declare function pick(obj: any, ...attr: any[]): any;
export declare function installTimerFunctions(obj: any, opts: any): void;
export declare function byteLength(obj: any): number;
/**
* Generates a random 8-characters string.
*/
export declare function randomString(): string;

65
node_modules/engine.io-client/build/cjs/util.js generated vendored Normal file
View File

@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pick = pick;
exports.installTimerFunctions = installTimerFunctions;
exports.byteLength = byteLength;
exports.randomString = randomString;
const globals_node_js_1 = require("./globals.node.js");
function pick(obj, ...attr) {
return attr.reduce((acc, k) => {
if (obj.hasOwnProperty(k)) {
acc[k] = obj[k];
}
return acc;
}, {});
}
// Keep a reference to the real timeout functions so they can be used when overridden
const NATIVE_SET_TIMEOUT = globals_node_js_1.globalThisShim.setTimeout;
const NATIVE_CLEAR_TIMEOUT = globals_node_js_1.globalThisShim.clearTimeout;
function installTimerFunctions(obj, opts) {
if (opts.useNativeTimers) {
obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globals_node_js_1.globalThisShim);
obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globals_node_js_1.globalThisShim);
}
else {
obj.setTimeoutFn = globals_node_js_1.globalThisShim.setTimeout.bind(globals_node_js_1.globalThisShim);
obj.clearTimeoutFn = globals_node_js_1.globalThisShim.clearTimeout.bind(globals_node_js_1.globalThisShim);
}
}
// base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)
const BASE64_OVERHEAD = 1.33;
// we could also have used `new Blob([obj]).size`, but it isn't supported in IE9
function byteLength(obj) {
if (typeof obj === "string") {
return utf8Length(obj);
}
// arraybuffer or blob
return Math.ceil((obj.byteLength || obj.size) * BASE64_OVERHEAD);
}
function utf8Length(str) {
let c = 0, length = 0;
for (let i = 0, l = str.length; i < l; i++) {
c = str.charCodeAt(i);
if (c < 0x80) {
length += 1;
}
else if (c < 0x800) {
length += 2;
}
else if (c < 0xd800 || c >= 0xe000) {
length += 3;
}
else {
i++;
length += 4;
}
}
return length;
}
/**
* Generates a random 8-characters string.
*/
function randomString() {
return (Date.now().toString(36).substring(3) +
Math.random().toString(36).substring(2, 5));
}

View File

@ -0,0 +1,3 @@
import { Socket } from "./socket.js";
declare const _default: (uri: any, opts: any) => Socket;
export default _default;

View File

@ -0,0 +1,2 @@
import { Socket } from "./socket.js";
export default (uri, opts) => new Socket(uri, opts);

View File

@ -0,0 +1 @@
export declare const hasCORS: boolean;

View File

@ -0,0 +1,11 @@
// imported from https://github.com/component/has-cors
let value = false;
try {
value = typeof XMLHttpRequest !== 'undefined' &&
'withCredentials' in new XMLHttpRequest();
}
catch (err) {
// if XMLHttp support is disabled in IE then it will throw
// when trying to create
}
export const hasCORS = value;

View File

@ -0,0 +1,15 @@
/**
* Compiles a querystring
* Returns string representation of the object
*
* @param {Object}
* @api private
*/
export declare function encode(obj: any): string;
/**
* Parses a simple querystring into an object
*
* @param {String} qs
* @api private
*/
export declare function decode(qs: any): {};

View File

@ -0,0 +1,34 @@
// imported from https://github.com/galkn/querystring
/**
* Compiles a querystring
* Returns string representation of the object
*
* @param {Object}
* @api private
*/
export function encode(obj) {
let str = '';
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
if (str.length)
str += '&';
str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
}
}
return str;
}
/**
* Parses a simple querystring into an object
*
* @param {String} qs
* @api private
*/
export function decode(qs) {
let qry = {};
let pairs = qs.split('&');
for (let i = 0, l = pairs.length; i < l; i++) {
let pair = pairs[i].split('=');
qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
return qry;
}

View File

@ -0,0 +1 @@
export declare function parse(str: string): any;

View File

@ -0,0 +1,64 @@
// imported from https://github.com/galkn/parseuri
/**
* Parses a URI
*
* Note: we could also have used the built-in URL object, but it isn't supported on all platforms.
*
* See:
* - https://developer.mozilla.org/en-US/docs/Web/API/URL
* - https://caniuse.com/url
* - https://www.rfc-editor.org/rfc/rfc3986#appendix-B
*
* History of the parse() method:
* - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c
* - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3
* - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242
*
* @author Steven Levithan <stevenlevithan.com> (MIT license)
* @api private
*/
const re = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
const parts = [
'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
];
export function parse(str) {
if (str.length > 8000) {
throw "URI too long";
}
const src = str, b = str.indexOf('['), e = str.indexOf(']');
if (b != -1 && e != -1) {
str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
}
let m = re.exec(str || ''), uri = {}, i = 14;
while (i--) {
uri[parts[i]] = m[i] || '';
}
if (b != -1 && e != -1) {
uri.source = src;
uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
uri.ipv6uri = true;
}
uri.pathNames = pathNames(uri, uri['path']);
uri.queryKey = queryKey(uri, uri['query']);
return uri;
}
function pathNames(obj, path) {
const regx = /\/{2,9}/g, names = path.replace(regx, "/").split("/");
if (path.slice(0, 1) == '/' || path.length === 0) {
names.splice(0, 1);
}
if (path.slice(-1) == '/') {
names.splice(names.length - 1, 1);
}
return names;
}
function queryKey(uri, query) {
const data = {};
query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {
if ($1) {
data[$1] = $2;
}
});
return data;
}

View File

@ -0,0 +1,4 @@
export declare const nextTick: (cb: any, setTimeoutFn: any) => any;
export declare const globalThisShim: any;
export declare const defaultBinaryType = "arraybuffer";
export declare function createCookieJar(): void;

View File

@ -0,0 +1,22 @@
export const nextTick = (() => {
const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
if (isPromiseAvailable) {
return (cb) => Promise.resolve().then(cb);
}
else {
return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
}
})();
export const globalThisShim = (() => {
if (typeof self !== "undefined") {
return self;
}
else if (typeof window !== "undefined") {
return window;
}
else {
return Function("return this")();
}
})();
export const defaultBinaryType = "arraybuffer";
export function createCookieJar() { }

View File

@ -0,0 +1,21 @@
export declare const nextTick: (callback: Function, ...args: any[]) => void;
export declare const globalThisShim: typeof globalThis;
export declare const defaultBinaryType = "nodebuffer";
export declare function createCookieJar(): CookieJar;
interface Cookie {
name: string;
value: string;
expires?: Date;
}
/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
*/
export declare function parse(setCookieString: string): Cookie;
export declare class CookieJar {
private _cookies;
parseCookies(values: string[]): void;
get cookies(): IterableIterator<[string, Cookie]>;
addCookies(xhr: any): void;
appendCookies(headers: Headers): void;
}
export {};

View File

@ -0,0 +1,91 @@
export const nextTick = process.nextTick;
export const globalThisShim = global;
export const defaultBinaryType = "nodebuffer";
export function createCookieJar() {
return new CookieJar();
}
/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
*/
export function parse(setCookieString) {
const parts = setCookieString.split("; ");
const i = parts[0].indexOf("=");
if (i === -1) {
return;
}
const name = parts[0].substring(0, i).trim();
if (!name.length) {
return;
}
let value = parts[0].substring(i + 1).trim();
if (value.charCodeAt(0) === 0x22) {
// remove double quotes
value = value.slice(1, -1);
}
const cookie = {
name,
value,
};
for (let j = 1; j < parts.length; j++) {
const subParts = parts[j].split("=");
if (subParts.length !== 2) {
continue;
}
const key = subParts[0].trim();
const value = subParts[1].trim();
switch (key) {
case "Expires":
cookie.expires = new Date(value);
break;
case "Max-Age":
const expiration = new Date();
expiration.setUTCSeconds(expiration.getUTCSeconds() + parseInt(value, 10));
cookie.expires = expiration;
break;
default:
// ignore other keys
}
}
return cookie;
}
export class CookieJar {
constructor() {
this._cookies = new Map();
}
parseCookies(values) {
if (!values) {
return;
}
values.forEach((value) => {
const parsed = parse(value);
if (parsed) {
this._cookies.set(parsed.name, parsed);
}
});
}
get cookies() {
const now = Date.now();
this._cookies.forEach((cookie, name) => {
var _a;
if (((_a = cookie.expires) === null || _a === void 0 ? void 0 : _a.getTime()) < now) {
this._cookies.delete(name);
}
});
return this._cookies.entries();
}
addCookies(xhr) {
const cookies = [];
for (const [name, cookie] of this.cookies) {
cookies.push(`${name}=${cookie.value}`);
}
if (cookies.length) {
xhr.setDisableHeaderCheck(true);
xhr.setRequestHeader("cookie", cookies.join("; "));
}
}
appendCookies(headers) {
for (const [name, cookie] of this.cookies) {
headers.append("cookie", `${name}=${cookie.value}`);
}
}
}

View File

@ -0,0 +1,15 @@
import { Socket } from "./socket.js";
export { Socket };
export { SocketOptions, SocketWithoutUpgrade, SocketWithUpgrade, } from "./socket.js";
export declare const protocol: number;
export { Transport, TransportError } from "./transport.js";
export { transports } from "./transports/index.js";
export { installTimerFunctions } from "./util.js";
export { parse } from "./contrib/parseuri.js";
export { nextTick } from "./globals.node.js";
export { Fetch } from "./transports/polling-fetch.js";
export { XHR as NodeXHR } from "./transports/polling-xhr.node.js";
export { XHR } from "./transports/polling-xhr.js";
export { WS as NodeWebSocket } from "./transports/websocket.node.js";
export { WS as WebSocket } from "./transports/websocket.js";
export { WT as WebTransport } from "./transports/webtransport.js";

15
node_modules/engine.io-client/build/esm-debug/index.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
import { Socket } from "./socket.js";
export { Socket };
export { SocketWithoutUpgrade, SocketWithUpgrade, } from "./socket.js";
export const protocol = Socket.protocol;
export { Transport, TransportError } from "./transport.js";
export { transports } from "./transports/index.js";
export { installTimerFunctions } from "./util.js";
export { parse } from "./contrib/parseuri.js";
export { nextTick } from "./globals.node.js";
export { Fetch } from "./transports/polling-fetch.js";
export { XHR as NodeXHR } from "./transports/polling-xhr.node.js";
export { XHR } from "./transports/polling-xhr.js";
export { WS as NodeWebSocket } from "./transports/websocket.node.js";
export { WS as WebSocket } from "./transports/websocket.js";
export { WT as WebTransport } from "./transports/webtransport.js";

View File

@ -0,0 +1,10 @@
{
"name": "engine.io-client",
"type": "module",
"browser": {
"ws": false,
"./transports/polling-xhr.node.js": "./transports/polling-xhr.js",
"./transports/websocket.node.js": "./transports/websocket.js",
"./globals.node.js": "./globals.js"
}
}

View File

@ -0,0 +1,482 @@
import { Emitter } from "@socket.io/component-emitter";
import type { Packet, BinaryType, RawData } from "engine.io-parser";
import { CloseDetails, Transport } from "./transport.js";
import { CookieJar } from "./globals.node.js";
export interface SocketOptions {
/**
* The host that we're connecting to. Set from the URI passed when connecting
*/
host?: string;
/**
* The hostname for our connection. Set from the URI passed when connecting
*/
hostname?: string;
/**
* If this is a secure connection. Set from the URI passed when connecting
*/
secure?: boolean;
/**
* The port for our connection. Set from the URI passed when connecting
*/
port?: string | number;
/**
* Any query parameters in our uri. Set from the URI passed when connecting
*/
query?: {
[key: string]: any;
};
/**
* `http.Agent` to use, defaults to `false` (NodeJS only)
*
* Note: the type should be "undefined | http.Agent | https.Agent | false", but this would break browser-only clients.
*
* @see https://nodejs.org/api/http.html#httprequestoptions-callback
*/
agent?: string | boolean;
/**
* Whether the client should try to upgrade the transport from
* long-polling to something better.
* @default true
*/
upgrade?: boolean;
/**
* Forces base 64 encoding for polling transport even when XHR2
* responseType is available and WebSocket even if the used standard
* supports binary.
*/
forceBase64?: boolean;
/**
* The param name to use as our timestamp key
* @default 't'
*/
timestampParam?: string;
/**
* Whether to add the timestamp with each transport request. Note: this
* is ignored if the browser is IE or Android, in which case requests
* are always stamped
* @default false
*/
timestampRequests?: boolean;
/**
* A list of transports to try (in order). Engine.io always attempts to
* connect directly with the first one, provided the feature detection test
* for it passes.
*
* @default ['polling','websocket', 'webtransport']
*/
transports?: ("polling" | "websocket" | "webtransport" | string)[] | TransportCtor[];
/**
* Whether all the transports should be tested, instead of just the first one.
*
* If set to `true`, the client will first try to connect with HTTP long-polling, and then with WebSocket in case of
* failure, and finally with WebTransport if the previous attempts have failed.
*
* If set to `false` (default), if the connection with HTTP long-polling fails, then the client will not test the
* other transports and will abort the connection.
*
* @default false
*/
tryAllTransports?: boolean;
/**
* If true and if the previous websocket connection to the server succeeded,
* the connection attempt will bypass the normal upgrade process and will
* initially try websocket. A connection attempt following a transport error
* will use the normal upgrade process. It is recommended you turn this on
* only when using SSL/TLS connections, or if you know that your network does
* not block websockets.
* @default false
*/
rememberUpgrade?: boolean;
/**
* Timeout for xhr-polling requests in milliseconds (0) (only for polling transport)
*/
requestTimeout?: number;
/**
* Transport options for Node.js client (headers etc)
*/
transportOptions?: Object;
/**
* (SSL) Certificate, Private key and CA certificates to use for SSL.
* Can be used in Node.js client environment to manually specify
* certificate information.
*/
pfx?: string;
/**
* (SSL) Private key to use for SSL. Can be used in Node.js client
* environment to manually specify certificate information.
*/
key?: string;
/**
* (SSL) A string or passphrase for the private key or pfx. Can be
* used in Node.js client environment to manually specify certificate
* information.
*/
passphrase?: string;
/**
* (SSL) Public x509 certificate to use. Can be used in Node.js client
* environment to manually specify certificate information.
*/
cert?: string;
/**
* (SSL) An authority certificate or array of authority certificates to
* check the remote host against.. Can be used in Node.js client
* environment to manually specify certificate information.
*/
ca?: string | string[];
/**
* (SSL) A string describing the ciphers to use or exclude. Consult the
* [cipher format list]
* (http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT) for
* details on the format.. Can be used in Node.js client environment to
* manually specify certificate information.
*/
ciphers?: string;
/**
* (SSL) If true, the server certificate is verified against the list of
* supplied CAs. An 'error' event is emitted if verification fails.
* Verification happens at the connection level, before the HTTP request
* is sent. Can be used in Node.js client environment to manually specify
* certificate information.
*/
rejectUnauthorized?: boolean;
/**
* Headers that will be passed for each request to the server (via xhr-polling and via websockets).
* These values then can be used during handshake or for special proxies.
*/
extraHeaders?: {
[header: string]: string;
};
/**
* Whether to include credentials (cookies, authorization headers, TLS
* client certificates, etc.) with cross-origin XHR polling requests
* @default false
*/
withCredentials?: boolean;
/**
* Whether to automatically close the connection whenever the beforeunload event is received.
* @default false
*/
closeOnBeforeunload?: boolean;
/**
* Whether to always use the native timeouts. This allows the client to
* reconnect when the native timeout functions are overridden, such as when
* mock clocks are installed.
* @default false
*/
useNativeTimers?: boolean;
/**
* Whether the heartbeat timer should be unref'ed, in order not to keep the Node.js event loop active.
*
* @see https://nodejs.org/api/timers.html#timeoutunref
* @default false
*/
autoUnref?: boolean;
/**
* parameters of the WebSocket permessage-deflate extension (see ws module api docs). Set to false to disable.
* @default false
*/
perMessageDeflate?: {
threshold: number;
};
/**
* The path to get our client file from, in the case of the server
* serving it
* @default '/engine.io'
*/
path?: string;
/**
* Whether we should add a trailing slash to the request path.
* @default true
*/
addTrailingSlash?: boolean;
/**
* Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols,
* so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to
* be able to handle different types of interactions depending on the specified protocol)
* @default []
*/
protocols?: string | string[];
}
type TransportCtor = {
new (o: any): Transport;
};
type BaseSocketOptions = Omit<SocketOptions, "transports"> & {
transports: TransportCtor[];
};
interface HandshakeData {
sid: string;
upgrades: string[];
pingInterval: number;
pingTimeout: number;
maxPayload: number;
}
interface SocketReservedEvents {
open: () => void;
handshake: (data: HandshakeData) => void;
packet: (packet: Packet) => void;
packetCreate: (packet: Packet) => void;
data: (data: RawData) => void;
message: (data: RawData) => void;
drain: () => void;
flush: () => void;
heartbeat: () => void;
ping: () => void;
pong: () => void;
error: (err: string | Error) => void;
upgrading: (transport: Transport) => void;
upgrade: (transport: Transport) => void;
upgradeError: (err: Error) => void;
close: (reason: string, description?: CloseDetails | Error) => void;
}
type SocketState = "opening" | "open" | "closing" | "closed";
interface WriteOptions {
compress?: boolean;
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes without upgrade mechanism, which means that it will keep the first low-level transport that
* successfully establishes the connection.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithoutUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithUpgrade
* @see Socket
*/
export declare class SocketWithoutUpgrade extends Emitter<Record<never, never>, Record<never, never>, SocketReservedEvents> {
id: string;
transport: Transport;
binaryType: BinaryType;
readyState: SocketState;
writeBuffer: Packet[];
protected readonly opts: BaseSocketOptions;
protected readonly transports: string[];
protected upgrading: boolean;
protected setTimeoutFn: typeof setTimeout;
private _prevBufferLen;
private _pingInterval;
private _pingTimeout;
private _maxPayload?;
private _pingTimeoutTimer;
/**
* The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
* callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
*/
private _pingTimeoutTime;
private clearTimeoutFn;
private readonly _beforeunloadEventListener;
private readonly _offlineEventListener;
private readonly secure;
private readonly hostname;
private readonly port;
private readonly _transportsByName;
/**
* The cookie jar will store the cookies sent by the server (Node. js only).
*/
readonly _cookieJar: CookieJar;
static priorWebsocketSuccess: boolean;
static protocol: number;
/**
* Socket constructor.
*
* @param {String|Object} uri - uri or options
* @param {Object} opts - options
*/
constructor(uri: string | BaseSocketOptions, opts: BaseSocketOptions);
/**
* Creates transport of the given type.
*
* @param {String} name - transport name
* @return {Transport}
* @private
*/
protected createTransport(name: string): Transport;
/**
* Initializes transport to use and starts probe.
*
* @private
*/
private _open;
/**
* Sets the current transport. Disables the existing one (if any).
*
* @private
*/
protected setTransport(transport: Transport): void;
/**
* Called when connection is deemed open.
*
* @private
*/
protected onOpen(): void;
/**
* Handles a packet.
*
* @private
*/
private _onPacket;
/**
* Called upon handshake completion.
*
* @param {Object} data - handshake obj
* @private
*/
protected onHandshake(data: HandshakeData): void;
/**
* Sets and resets ping timeout timer based on server pings.
*
* @private
*/
private _resetPingTimeout;
/**
* Called on `drain` event
*
* @private
*/
private _onDrain;
/**
* Flush write buffers.
*
* @private
*/
protected flush(): void;
/**
* Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
* long-polling)
*
* @private
*/
private _getWritablePackets;
/**
* Checks whether the heartbeat timer has expired but the socket has not yet been notified.
*
* Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
* `write()` method then the message would not be buffered by the Socket.IO client.
*
* @return {boolean}
* @private
*/
_hasPingExpired(): boolean;
/**
* Sends a message.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
write(msg: RawData, options?: WriteOptions, fn?: () => void): this;
/**
* Sends a message. Alias of {@link Socket#write}.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
send(msg: RawData, options?: WriteOptions, fn?: () => void): this;
/**
* Sends a packet.
*
* @param {String} type: packet type.
* @param {String} data.
* @param {Object} options.
* @param {Function} fn - callback function.
* @private
*/
private _sendPacket;
/**
* Closes the connection.
*/
close(): this;
/**
* Called upon transport error
*
* @private
*/
private _onError;
/**
* Called upon transport close.
*
* @private
*/
private _onClose;
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see Socket
*/
export declare class SocketWithUpgrade extends SocketWithoutUpgrade {
private _upgrades;
onOpen(): void;
/**
* Probes a transport.
*
* @param {String} name - transport name
* @private
*/
private _probe;
onHandshake(data: HandshakeData): void;
/**
* Filters upgrades, returning only those matching client transports.
*
* @param {Array} upgrades - server upgrades
* @private
*/
private _filterUpgrades;
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* @example
* import { Socket } from "engine.io-client";
*
* const socket = new Socket();
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see SocketWithUpgrade
*/
export declare class Socket extends SocketWithUpgrade {
constructor(uri?: string, opts?: SocketOptions);
constructor(opts: SocketOptions);
}
export {};

756
node_modules/engine.io-client/build/esm-debug/socket.js generated vendored Normal file
View File

@ -0,0 +1,756 @@
import { transports as DEFAULT_TRANSPORTS } from "./transports/index.js";
import { installTimerFunctions, byteLength } from "./util.js";
import { decode } from "./contrib/parseqs.js";
import { parse } from "./contrib/parseuri.js";
import { Emitter } from "@socket.io/component-emitter";
import { protocol } from "engine.io-parser";
import { createCookieJar, defaultBinaryType, nextTick, } from "./globals.node.js";
import debugModule from "debug"; // debug()
const debug = debugModule("engine.io-client:socket"); // debug()
const withEventListeners = typeof addEventListener === "function" &&
typeof removeEventListener === "function";
const OFFLINE_EVENT_LISTENERS = [];
if (withEventListeners) {
// within a ServiceWorker, any event handler for the 'offline' event must be added on the initial evaluation of the
// script, so we create one single event listener here which will forward the event to the socket instances
addEventListener("offline", () => {
debug("closing %d connection(s) because the network was lost", OFFLINE_EVENT_LISTENERS.length);
OFFLINE_EVENT_LISTENERS.forEach((listener) => listener());
}, false);
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes without upgrade mechanism, which means that it will keep the first low-level transport that
* successfully establishes the connection.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithoutUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithUpgrade
* @see Socket
*/
export class SocketWithoutUpgrade extends Emitter {
/**
* Socket constructor.
*
* @param {String|Object} uri - uri or options
* @param {Object} opts - options
*/
constructor(uri, opts) {
super();
this.binaryType = defaultBinaryType;
this.writeBuffer = [];
this._prevBufferLen = 0;
this._pingInterval = -1;
this._pingTimeout = -1;
this._maxPayload = -1;
/**
* The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
* callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
*/
this._pingTimeoutTime = Infinity;
if (uri && "object" === typeof uri) {
opts = uri;
uri = null;
}
if (uri) {
const parsedUri = parse(uri);
opts.hostname = parsedUri.host;
opts.secure =
parsedUri.protocol === "https" || parsedUri.protocol === "wss";
opts.port = parsedUri.port;
if (parsedUri.query)
opts.query = parsedUri.query;
}
else if (opts.host) {
opts.hostname = parse(opts.host).host;
}
installTimerFunctions(this, opts);
this.secure =
null != opts.secure
? opts.secure
: typeof location !== "undefined" && "https:" === location.protocol;
if (opts.hostname && !opts.port) {
// if no port is specified manually, use the protocol default
opts.port = this.secure ? "443" : "80";
}
this.hostname =
opts.hostname ||
(typeof location !== "undefined" ? location.hostname : "localhost");
this.port =
opts.port ||
(typeof location !== "undefined" && location.port
? location.port
: this.secure
? "443"
: "80");
this.transports = [];
this._transportsByName = {};
opts.transports.forEach((t) => {
const transportName = t.prototype.name;
this.transports.push(transportName);
this._transportsByName[transportName] = t;
});
this.opts = Object.assign({
path: "/engine.io",
agent: false,
withCredentials: false,
upgrade: true,
timestampParam: "t",
rememberUpgrade: false,
addTrailingSlash: true,
rejectUnauthorized: true,
perMessageDeflate: {
threshold: 1024,
},
transportOptions: {},
closeOnBeforeunload: false,
}, opts);
this.opts.path =
this.opts.path.replace(/\/$/, "") +
(this.opts.addTrailingSlash ? "/" : "");
if (typeof this.opts.query === "string") {
this.opts.query = decode(this.opts.query);
}
if (withEventListeners) {
if (this.opts.closeOnBeforeunload) {
// Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
// ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
// closed/reloaded)
this._beforeunloadEventListener = () => {
if (this.transport) {
// silently close the transport
this.transport.removeAllListeners();
this.transport.close();
}
};
addEventListener("beforeunload", this._beforeunloadEventListener, false);
}
if (this.hostname !== "localhost") {
debug("adding listener for the 'offline' event");
this._offlineEventListener = () => {
this._onClose("transport close", {
description: "network connection lost",
});
};
OFFLINE_EVENT_LISTENERS.push(this._offlineEventListener);
}
}
if (this.opts.withCredentials) {
this._cookieJar = createCookieJar();
}
this._open();
}
/**
* Creates transport of the given type.
*
* @param {String} name - transport name
* @return {Transport}
* @private
*/
createTransport(name) {
debug('creating transport "%s"', name);
const query = Object.assign({}, this.opts.query);
// append engine.io protocol identifier
query.EIO = protocol;
// transport name
query.transport = name;
// session id if we already have one
if (this.id)
query.sid = this.id;
const opts = Object.assign({}, this.opts, {
query,
socket: this,
hostname: this.hostname,
secure: this.secure,
port: this.port,
}, this.opts.transportOptions[name]);
debug("options: %j", opts);
return new this._transportsByName[name](opts);
}
/**
* Initializes transport to use and starts probe.
*
* @private
*/
_open() {
if (this.transports.length === 0) {
// Emit error on next tick so it can be listened to
this.setTimeoutFn(() => {
this.emitReserved("error", "No transports available");
}, 0);
return;
}
const transportName = this.opts.rememberUpgrade &&
SocketWithoutUpgrade.priorWebsocketSuccess &&
this.transports.indexOf("websocket") !== -1
? "websocket"
: this.transports[0];
this.readyState = "opening";
const transport = this.createTransport(transportName);
transport.open();
this.setTransport(transport);
}
/**
* Sets the current transport. Disables the existing one (if any).
*
* @private
*/
setTransport(transport) {
debug("setting transport %s", transport.name);
if (this.transport) {
debug("clearing existing transport %s", this.transport.name);
this.transport.removeAllListeners();
}
// set up transport
this.transport = transport;
// set up transport listeners
transport
.on("drain", this._onDrain.bind(this))
.on("packet", this._onPacket.bind(this))
.on("error", this._onError.bind(this))
.on("close", (reason) => this._onClose("transport close", reason));
}
/**
* Called when connection is deemed open.
*
* @private
*/
onOpen() {
debug("socket open");
this.readyState = "open";
SocketWithoutUpgrade.priorWebsocketSuccess =
"websocket" === this.transport.name;
this.emitReserved("open");
this.flush();
}
/**
* Handles a packet.
*
* @private
*/
_onPacket(packet) {
if ("opening" === this.readyState ||
"open" === this.readyState ||
"closing" === this.readyState) {
debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
this.emitReserved("packet", packet);
// Socket is live - any packet counts
this.emitReserved("heartbeat");
switch (packet.type) {
case "open":
this.onHandshake(JSON.parse(packet.data));
break;
case "ping":
this._sendPacket("pong");
this.emitReserved("ping");
this.emitReserved("pong");
this._resetPingTimeout();
break;
case "error":
const err = new Error("server error");
// @ts-ignore
err.code = packet.data;
this._onError(err);
break;
case "message":
this.emitReserved("data", packet.data);
this.emitReserved("message", packet.data);
break;
}
}
else {
debug('packet received with socket readyState "%s"', this.readyState);
}
}
/**
* Called upon handshake completion.
*
* @param {Object} data - handshake obj
* @private
*/
onHandshake(data) {
this.emitReserved("handshake", data);
this.id = data.sid;
this.transport.query.sid = data.sid;
this._pingInterval = data.pingInterval;
this._pingTimeout = data.pingTimeout;
this._maxPayload = data.maxPayload;
this.onOpen();
// In case open handler closes socket
if ("closed" === this.readyState)
return;
this._resetPingTimeout();
}
/**
* Sets and resets ping timeout timer based on server pings.
*
* @private
*/
_resetPingTimeout() {
this.clearTimeoutFn(this._pingTimeoutTimer);
const delay = this._pingInterval + this._pingTimeout;
this._pingTimeoutTime = Date.now() + delay;
this._pingTimeoutTimer = this.setTimeoutFn(() => {
this._onClose("ping timeout");
}, delay);
if (this.opts.autoUnref) {
this._pingTimeoutTimer.unref();
}
}
/**
* Called on `drain` event
*
* @private
*/
_onDrain() {
this.writeBuffer.splice(0, this._prevBufferLen);
// setting prevBufferLen = 0 is very important
// for example, when upgrading, upgrade packet is sent over,
// and a nonzero prevBufferLen could cause problems on `drain`
this._prevBufferLen = 0;
if (0 === this.writeBuffer.length) {
this.emitReserved("drain");
}
else {
this.flush();
}
}
/**
* Flush write buffers.
*
* @private
*/
flush() {
if ("closed" !== this.readyState &&
this.transport.writable &&
!this.upgrading &&
this.writeBuffer.length) {
const packets = this._getWritablePackets();
debug("flushing %d packets in socket", packets.length);
this.transport.send(packets);
// keep track of current length of writeBuffer
// splice writeBuffer and callbackBuffer on `drain`
this._prevBufferLen = packets.length;
this.emitReserved("flush");
}
}
/**
* Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
* long-polling)
*
* @private
*/
_getWritablePackets() {
const shouldCheckPayloadSize = this._maxPayload &&
this.transport.name === "polling" &&
this.writeBuffer.length > 1;
if (!shouldCheckPayloadSize) {
return this.writeBuffer;
}
let payloadSize = 1; // first packet type
for (let i = 0; i < this.writeBuffer.length; i++) {
const data = this.writeBuffer[i].data;
if (data) {
payloadSize += byteLength(data);
}
if (i > 0 && payloadSize > this._maxPayload) {
debug("only send %d out of %d packets", i, this.writeBuffer.length);
return this.writeBuffer.slice(0, i);
}
payloadSize += 2; // separator + packet type
}
debug("payload size is %d (max: %d)", payloadSize, this._maxPayload);
return this.writeBuffer;
}
/**
* Checks whether the heartbeat timer has expired but the socket has not yet been notified.
*
* Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
* `write()` method then the message would not be buffered by the Socket.IO client.
*
* @return {boolean}
* @private
*/
/* private */ _hasPingExpired() {
if (!this._pingTimeoutTime)
return true;
const hasExpired = Date.now() > this._pingTimeoutTime;
if (hasExpired) {
debug("throttled timer detected, scheduling connection close");
this._pingTimeoutTime = 0;
nextTick(() => {
this._onClose("ping timeout");
}, this.setTimeoutFn);
}
return hasExpired;
}
/**
* Sends a message.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
write(msg, options, fn) {
this._sendPacket("message", msg, options, fn);
return this;
}
/**
* Sends a message. Alias of {@link Socket#write}.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
send(msg, options, fn) {
this._sendPacket("message", msg, options, fn);
return this;
}
/**
* Sends a packet.
*
* @param {String} type: packet type.
* @param {String} data.
* @param {Object} options.
* @param {Function} fn - callback function.
* @private
*/
_sendPacket(type, data, options, fn) {
if ("function" === typeof data) {
fn = data;
data = undefined;
}
if ("function" === typeof options) {
fn = options;
options = null;
}
if ("closing" === this.readyState || "closed" === this.readyState) {
return;
}
options = options || {};
options.compress = false !== options.compress;
const packet = {
type: type,
data: data,
options: options,
};
this.emitReserved("packetCreate", packet);
this.writeBuffer.push(packet);
if (fn)
this.once("flush", fn);
this.flush();
}
/**
* Closes the connection.
*/
close() {
const close = () => {
this._onClose("forced close");
debug("socket closing - telling transport to close");
this.transport.close();
};
const cleanupAndClose = () => {
this.off("upgrade", cleanupAndClose);
this.off("upgradeError", cleanupAndClose);
close();
};
const waitForUpgrade = () => {
// wait for upgrade to finish since we can't send packets while pausing a transport
this.once("upgrade", cleanupAndClose);
this.once("upgradeError", cleanupAndClose);
};
if ("opening" === this.readyState || "open" === this.readyState) {
this.readyState = "closing";
if (this.writeBuffer.length) {
this.once("drain", () => {
if (this.upgrading) {
waitForUpgrade();
}
else {
close();
}
});
}
else if (this.upgrading) {
waitForUpgrade();
}
else {
close();
}
}
return this;
}
/**
* Called upon transport error
*
* @private
*/
_onError(err) {
debug("socket error %j", err);
SocketWithoutUpgrade.priorWebsocketSuccess = false;
if (this.opts.tryAllTransports &&
this.transports.length > 1 &&
this.readyState === "opening") {
debug("trying next transport");
this.transports.shift();
return this._open();
}
this.emitReserved("error", err);
this._onClose("transport error", err);
}
/**
* Called upon transport close.
*
* @private
*/
_onClose(reason, description) {
if ("opening" === this.readyState ||
"open" === this.readyState ||
"closing" === this.readyState) {
debug('socket close with reason: "%s"', reason);
// clear timers
this.clearTimeoutFn(this._pingTimeoutTimer);
// stop event from firing again for transport
this.transport.removeAllListeners("close");
// ensure transport won't stay open
this.transport.close();
// ignore further transport communication
this.transport.removeAllListeners();
if (withEventListeners) {
if (this._beforeunloadEventListener) {
removeEventListener("beforeunload", this._beforeunloadEventListener, false);
}
if (this._offlineEventListener) {
const i = OFFLINE_EVENT_LISTENERS.indexOf(this._offlineEventListener);
if (i !== -1) {
debug("removing listener for the 'offline' event");
OFFLINE_EVENT_LISTENERS.splice(i, 1);
}
}
}
// set ready state
this.readyState = "closed";
// clear session id
this.id = null;
// emit close event
this.emitReserved("close", reason, description);
// clean buffers after, so users can still
// grab the buffers on `close` event
this.writeBuffer = [];
this._prevBufferLen = 0;
}
}
}
SocketWithoutUpgrade.protocol = protocol;
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see Socket
*/
export class SocketWithUpgrade extends SocketWithoutUpgrade {
constructor() {
super(...arguments);
this._upgrades = [];
}
onOpen() {
super.onOpen();
if ("open" === this.readyState && this.opts.upgrade) {
debug("starting upgrade probes");
for (let i = 0; i < this._upgrades.length; i++) {
this._probe(this._upgrades[i]);
}
}
}
/**
* Probes a transport.
*
* @param {String} name - transport name
* @private
*/
_probe(name) {
debug('probing transport "%s"', name);
let transport = this.createTransport(name);
let failed = false;
SocketWithoutUpgrade.priorWebsocketSuccess = false;
const onTransportOpen = () => {
if (failed)
return;
debug('probe transport "%s" opened', name);
transport.send([{ type: "ping", data: "probe" }]);
transport.once("packet", (msg) => {
if (failed)
return;
if ("pong" === msg.type && "probe" === msg.data) {
debug('probe transport "%s" pong', name);
this.upgrading = true;
this.emitReserved("upgrading", transport);
if (!transport)
return;
SocketWithoutUpgrade.priorWebsocketSuccess =
"websocket" === transport.name;
debug('pausing current transport "%s"', this.transport.name);
this.transport.pause(() => {
if (failed)
return;
if ("closed" === this.readyState)
return;
debug("changing transport and sending upgrade packet");
cleanup();
this.setTransport(transport);
transport.send([{ type: "upgrade" }]);
this.emitReserved("upgrade", transport);
transport = null;
this.upgrading = false;
this.flush();
});
}
else {
debug('probe transport "%s" failed', name);
const err = new Error("probe error");
// @ts-ignore
err.transport = transport.name;
this.emitReserved("upgradeError", err);
}
});
};
function freezeTransport() {
if (failed)
return;
// Any callback called by transport should be ignored since now
failed = true;
cleanup();
transport.close();
transport = null;
}
// Handle any error that happens while probing
const onerror = (err) => {
const error = new Error("probe error: " + err);
// @ts-ignore
error.transport = transport.name;
freezeTransport();
debug('probe transport "%s" failed because of error: %s', name, err);
this.emitReserved("upgradeError", error);
};
function onTransportClose() {
onerror("transport closed");
}
// When the socket is closed while we're probing
function onclose() {
onerror("socket closed");
}
// When the socket is upgraded while we're probing
function onupgrade(to) {
if (transport && to.name !== transport.name) {
debug('"%s" works - aborting "%s"', to.name, transport.name);
freezeTransport();
}
}
// Remove all listeners on the transport and on self
const cleanup = () => {
transport.removeListener("open", onTransportOpen);
transport.removeListener("error", onerror);
transport.removeListener("close", onTransportClose);
this.off("close", onclose);
this.off("upgrading", onupgrade);
};
transport.once("open", onTransportOpen);
transport.once("error", onerror);
transport.once("close", onTransportClose);
this.once("close", onclose);
this.once("upgrading", onupgrade);
if (this._upgrades.indexOf("webtransport") !== -1 &&
name !== "webtransport") {
// favor WebTransport
this.setTimeoutFn(() => {
if (!failed) {
transport.open();
}
}, 200);
}
else {
transport.open();
}
}
onHandshake(data) {
this._upgrades = this._filterUpgrades(data.upgrades);
super.onHandshake(data);
}
/**
* Filters upgrades, returning only those matching client transports.
*
* @param {Array} upgrades - server upgrades
* @private
*/
_filterUpgrades(upgrades) {
const filteredUpgrades = [];
for (let i = 0; i < upgrades.length; i++) {
if (~this.transports.indexOf(upgrades[i]))
filteredUpgrades.push(upgrades[i]);
}
return filteredUpgrades;
}
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* @example
* import { Socket } from "engine.io-client";
*
* const socket = new Socket();
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see SocketWithUpgrade
*/
export class Socket extends SocketWithUpgrade {
constructor(uri, opts = {}) {
const o = typeof uri === "object" ? uri : opts;
if (!o.transports ||
(o.transports && typeof o.transports[0] === "string")) {
o.transports = (o.transports || ["polling", "websocket", "webtransport"])
.map((transportName) => DEFAULT_TRANSPORTS[transportName])
.filter((t) => !!t);
}
super(uri, o);
}
}

View File

@ -0,0 +1,106 @@
import type { Packet, RawData } from "engine.io-parser";
import { Emitter } from "@socket.io/component-emitter";
import type { Socket, SocketOptions } from "./socket.js";
export declare class TransportError extends Error {
readonly description: any;
readonly context: any;
readonly type = "TransportError";
constructor(reason: string, description: any, context: any);
}
export interface CloseDetails {
description: string;
context?: unknown;
}
interface TransportReservedEvents {
open: () => void;
error: (err: TransportError) => void;
packet: (packet: Packet) => void;
close: (details?: CloseDetails) => void;
poll: () => void;
pollComplete: () => void;
drain: () => void;
}
type TransportState = "opening" | "open" | "closed" | "pausing" | "paused";
export declare abstract class Transport extends Emitter<Record<never, never>, Record<never, never>, TransportReservedEvents> {
query: Record<string, string>;
writable: boolean;
protected opts: SocketOptions;
protected supportsBinary: boolean;
protected readyState: TransportState;
protected socket: Socket;
protected setTimeoutFn: typeof setTimeout;
/**
* Transport abstract constructor.
*
* @param {Object} opts - options
* @protected
*/
constructor(opts: any);
/**
* Emits an error.
*
* @param {String} reason
* @param description
* @param context - the error context
* @return {Transport} for chaining
* @protected
*/
protected onError(reason: string, description: any, context?: any): this;
/**
* Opens the transport.
*/
open(): this;
/**
* Closes the transport.
*/
close(): this;
/**
* Sends multiple packets.
*
* @param {Array} packets
*/
send(packets: any): void;
/**
* Called upon open
*
* @protected
*/
protected onOpen(): void;
/**
* Called with data.
*
* @param {String} data
* @protected
*/
protected onData(data: RawData): void;
/**
* Called with a decoded packet.
*
* @protected
*/
protected onPacket(packet: Packet): void;
/**
* Called upon close.
*
* @protected
*/
protected onClose(details?: CloseDetails): void;
/**
* The name of the transport
*/
abstract get name(): string;
/**
* Pauses the transport, in order not to lose packets during an upgrade.
*
* @param onPause
*/
pause(onPause: () => void): void;
protected createUri(schema: string, query?: Record<string, unknown>): string;
private _hostname;
private _port;
private _query;
protected abstract doOpen(): any;
protected abstract doClose(): any;
protected abstract write(packets: Packet[]): any;
}
export {};

View File

@ -0,0 +1,145 @@
import { decodePacket } from "engine.io-parser";
import { Emitter } from "@socket.io/component-emitter";
import { installTimerFunctions } from "./util.js";
import { encode } from "./contrib/parseqs.js";
import debugModule from "debug"; // debug()
const debug = debugModule("engine.io-client:transport"); // debug()
export class TransportError extends Error {
constructor(reason, description, context) {
super(reason);
this.description = description;
this.context = context;
this.type = "TransportError";
}
}
export class Transport extends Emitter {
/**
* Transport abstract constructor.
*
* @param {Object} opts - options
* @protected
*/
constructor(opts) {
super();
this.writable = false;
installTimerFunctions(this, opts);
this.opts = opts;
this.query = opts.query;
this.socket = opts.socket;
this.supportsBinary = !opts.forceBase64;
}
/**
* Emits an error.
*
* @param {String} reason
* @param description
* @param context - the error context
* @return {Transport} for chaining
* @protected
*/
onError(reason, description, context) {
super.emitReserved("error", new TransportError(reason, description, context));
return this;
}
/**
* Opens the transport.
*/
open() {
this.readyState = "opening";
this.doOpen();
return this;
}
/**
* Closes the transport.
*/
close() {
if (this.readyState === "opening" || this.readyState === "open") {
this.doClose();
this.onClose();
}
return this;
}
/**
* Sends multiple packets.
*
* @param {Array} packets
*/
send(packets) {
if (this.readyState === "open") {
this.write(packets);
}
else {
// this might happen if the transport was silently closed in the beforeunload event handler
debug("transport is not open, discarding packets");
}
}
/**
* Called upon open
*
* @protected
*/
onOpen() {
this.readyState = "open";
this.writable = true;
super.emitReserved("open");
}
/**
* Called with data.
*
* @param {String} data
* @protected
*/
onData(data) {
const packet = decodePacket(data, this.socket.binaryType);
this.onPacket(packet);
}
/**
* Called with a decoded packet.
*
* @protected
*/
onPacket(packet) {
super.emitReserved("packet", packet);
}
/**
* Called upon close.
*
* @protected
*/
onClose(details) {
this.readyState = "closed";
super.emitReserved("close", details);
}
/**
* Pauses the transport, in order not to lose packets during an upgrade.
*
* @param onPause
*/
pause(onPause) { }
createUri(schema, query = {}) {
return (schema +
"://" +
this._hostname() +
this._port() +
this.opts.path +
this._query(query));
}
_hostname() {
const hostname = this.opts.hostname;
return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
}
_port() {
if (this.opts.port &&
((this.opts.secure && Number(this.opts.port !== 443)) ||
(!this.opts.secure && Number(this.opts.port) !== 80))) {
return ":" + this.opts.port;
}
else {
return "";
}
}
_query(query) {
const encodedQuery = encode(query);
return encodedQuery.length ? "?" + encodedQuery : "";
}
}

View File

@ -0,0 +1,8 @@
import { XHR } from "./polling-xhr.node.js";
import { WS } from "./websocket.node.js";
import { WT } from "./webtransport.js";
export declare const transports: {
websocket: typeof WS;
webtransport: typeof WT;
polling: typeof XHR;
};

View File

@ -0,0 +1,8 @@
import { XHR } from "./polling-xhr.node.js";
import { WS } from "./websocket.node.js";
import { WT } from "./webtransport.js";
export const transports = {
websocket: WS,
webtransport: WT,
polling: XHR,
};

View File

@ -0,0 +1,15 @@
import { Polling } from "./polling.js";
/**
* HTTP long-polling based on the built-in `fetch()` method.
*
* Usage: browser, Node.js (since v18), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/fetch
* @see https://caniuse.com/fetch
* @see https://nodejs.org/api/globals.html#fetch
*/
export declare class Fetch extends Polling {
doPoll(): void;
doWrite(data: string, callback: () => void): void;
private _fetch;
}

View File

@ -0,0 +1,56 @@
import { Polling } from "./polling.js";
/**
* HTTP long-polling based on the built-in `fetch()` method.
*
* Usage: browser, Node.js (since v18), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/fetch
* @see https://caniuse.com/fetch
* @see https://nodejs.org/api/globals.html#fetch
*/
export class Fetch extends Polling {
doPoll() {
this._fetch()
.then((res) => {
if (!res.ok) {
return this.onError("fetch read error", res.status, res);
}
res.text().then((data) => this.onData(data));
})
.catch((err) => {
this.onError("fetch read error", err);
});
}
doWrite(data, callback) {
this._fetch(data)
.then((res) => {
if (!res.ok) {
return this.onError("fetch write error", res.status, res);
}
callback();
})
.catch((err) => {
this.onError("fetch write error", err);
});
}
_fetch(data) {
var _a;
const isPost = data !== undefined;
const headers = new Headers(this.opts.extraHeaders);
if (isPost) {
headers.set("content-type", "text/plain;charset=UTF-8");
}
(_a = this.socket._cookieJar) === null || _a === void 0 ? void 0 : _a.appendCookies(headers);
return fetch(this.uri(), {
method: isPost ? "POST" : "GET",
body: isPost ? data : null,
headers,
credentials: this.opts.withCredentials ? "include" : "omit",
}).then((res) => {
var _a;
// @ts-ignore getSetCookie() was added in Node.js v19.7.0
(_a = this.socket._cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(res.headers.getSetCookie());
return res;
});
}
}

View File

@ -0,0 +1,108 @@
import { Polling } from "./polling.js";
import { Emitter } from "@socket.io/component-emitter";
import type { SocketOptions } from "../socket.js";
import type { CookieJar } from "../globals.node.js";
import type { RawData } from "engine.io-parser";
export declare abstract class BaseXHR extends Polling {
protected readonly xd: boolean;
private pollXhr;
/**
* XHR Polling constructor.
*
* @param {Object} opts
* @package
*/
constructor(opts: any);
/**
* Creates a request.
*
* @private
*/
abstract request(opts?: Record<string, any>): any;
/**
* Sends data.
*
* @param {String} data to send.
* @param {Function} called upon flush.
* @private
*/
doWrite(data: any, fn: any): void;
/**
* Starts a poll cycle.
*
* @private
*/
doPoll(): void;
}
interface RequestReservedEvents {
success: () => void;
data: (data: RawData) => void;
error: (err: number | Error, context: unknown) => void;
}
export type RequestOptions = SocketOptions & {
method?: string;
data?: RawData;
xd: boolean;
cookieJar: CookieJar;
};
export declare class Request extends Emitter<Record<never, never>, Record<never, never>, RequestReservedEvents> {
private readonly createRequest;
private readonly _opts;
private readonly _method;
private readonly _uri;
private readonly _data;
private _xhr;
private setTimeoutFn;
private _index;
static requestsCount: number;
static requests: {};
/**
* Request constructor
*
* @param {Object} options
* @package
*/
constructor(createRequest: (opts: RequestOptions) => XMLHttpRequest, uri: string, opts: RequestOptions);
/**
* Creates the XHR object and sends the request.
*
* @private
*/
private _create;
/**
* Called upon error.
*
* @private
*/
private _onError;
/**
* Cleans up house.
*
* @private
*/
private _cleanup;
/**
* Called upon load.
*
* @private
*/
private _onLoad;
/**
* Aborts the request.
*
* @package
*/
abort(): void;
}
/**
* HTTP long-polling based on the built-in `XMLHttpRequest` object.
*
* Usage: browser
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
export declare class XHR extends BaseXHR {
constructor(opts: any);
request(opts?: Record<string, any>): Request;
}
export {};

View File

@ -0,0 +1,276 @@
import { Polling } from "./polling.js";
import { Emitter } from "@socket.io/component-emitter";
import { installTimerFunctions, pick } from "../util.js";
import { globalThisShim as globalThis } from "../globals.node.js";
import { hasCORS } from "../contrib/has-cors.js";
import debugModule from "debug"; // debug()
const debug = debugModule("engine.io-client:polling"); // debug()
function empty() { }
export class BaseXHR extends Polling {
/**
* XHR Polling constructor.
*
* @param {Object} opts
* @package
*/
constructor(opts) {
super(opts);
if (typeof location !== "undefined") {
const isSSL = "https:" === location.protocol;
let port = location.port;
// some user agents have empty `location.port`
if (!port) {
port = isSSL ? "443" : "80";
}
this.xd =
(typeof location !== "undefined" &&
opts.hostname !== location.hostname) ||
port !== opts.port;
}
}
/**
* Sends data.
*
* @param {String} data to send.
* @param {Function} called upon flush.
* @private
*/
doWrite(data, fn) {
const req = this.request({
method: "POST",
data: data,
});
req.on("success", fn);
req.on("error", (xhrStatus, context) => {
this.onError("xhr post error", xhrStatus, context);
});
}
/**
* Starts a poll cycle.
*
* @private
*/
doPoll() {
debug("xhr poll");
const req = this.request();
req.on("data", this.onData.bind(this));
req.on("error", (xhrStatus, context) => {
this.onError("xhr poll error", xhrStatus, context);
});
this.pollXhr = req;
}
}
export class Request extends Emitter {
/**
* Request constructor
*
* @param {Object} options
* @package
*/
constructor(createRequest, uri, opts) {
super();
this.createRequest = createRequest;
installTimerFunctions(this, opts);
this._opts = opts;
this._method = opts.method || "GET";
this._uri = uri;
this._data = undefined !== opts.data ? opts.data : null;
this._create();
}
/**
* Creates the XHR object and sends the request.
*
* @private
*/
_create() {
var _a;
const opts = pick(this._opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
opts.xdomain = !!this._opts.xd;
const xhr = (this._xhr = this.createRequest(opts));
try {
debug("xhr open %s: %s", this._method, this._uri);
xhr.open(this._method, this._uri, true);
try {
if (this._opts.extraHeaders) {
// @ts-ignore
xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
for (let i in this._opts.extraHeaders) {
if (this._opts.extraHeaders.hasOwnProperty(i)) {
xhr.setRequestHeader(i, this._opts.extraHeaders[i]);
}
}
}
}
catch (e) { }
if ("POST" === this._method) {
try {
xhr.setRequestHeader("Content-type", "text/plain;charset=UTF-8");
}
catch (e) { }
}
try {
xhr.setRequestHeader("Accept", "*/*");
}
catch (e) { }
(_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
// ie6 check
if ("withCredentials" in xhr) {
xhr.withCredentials = this._opts.withCredentials;
}
if (this._opts.requestTimeout) {
xhr.timeout = this._opts.requestTimeout;
}
xhr.onreadystatechange = () => {
var _a;
if (xhr.readyState === 3) {
(_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(
// @ts-ignore
xhr.getResponseHeader("set-cookie"));
}
if (4 !== xhr.readyState)
return;
if (200 === xhr.status || 1223 === xhr.status) {
this._onLoad();
}
else {
// make sure the `error` event handler that's user-set
// does not throw in the same tick and gets caught here
this.setTimeoutFn(() => {
this._onError(typeof xhr.status === "number" ? xhr.status : 0);
}, 0);
}
};
debug("xhr data %s", this._data);
xhr.send(this._data);
}
catch (e) {
// Need to defer since .create() is called directly from the constructor
// and thus the 'error' event can only be only bound *after* this exception
// occurs. Therefore, also, we cannot throw here at all.
this.setTimeoutFn(() => {
this._onError(e);
}, 0);
return;
}
if (typeof document !== "undefined") {
this._index = Request.requestsCount++;
Request.requests[this._index] = this;
}
}
/**
* Called upon error.
*
* @private
*/
_onError(err) {
this.emitReserved("error", err, this._xhr);
this._cleanup(true);
}
/**
* Cleans up house.
*
* @private
*/
_cleanup(fromError) {
if ("undefined" === typeof this._xhr || null === this._xhr) {
return;
}
this._xhr.onreadystatechange = empty;
if (fromError) {
try {
this._xhr.abort();
}
catch (e) { }
}
if (typeof document !== "undefined") {
delete Request.requests[this._index];
}
this._xhr = null;
}
/**
* Called upon load.
*
* @private
*/
_onLoad() {
const data = this._xhr.responseText;
if (data !== null) {
this.emitReserved("data", data);
this.emitReserved("success");
this._cleanup();
}
}
/**
* Aborts the request.
*
* @package
*/
abort() {
this._cleanup();
}
}
Request.requestsCount = 0;
Request.requests = {};
/**
* Aborts pending requests when unloading the window. This is needed to prevent
* memory leaks (e.g. when using IE) and to ensure that no spurious error is
* emitted.
*/
if (typeof document !== "undefined") {
// @ts-ignore
if (typeof attachEvent === "function") {
// @ts-ignore
attachEvent("onunload", unloadHandler);
}
else if (typeof addEventListener === "function") {
const terminationEvent = "onpagehide" in globalThis ? "pagehide" : "unload";
addEventListener(terminationEvent, unloadHandler, false);
}
}
function unloadHandler() {
for (let i in Request.requests) {
if (Request.requests.hasOwnProperty(i)) {
Request.requests[i].abort();
}
}
}
const hasXHR2 = (function () {
const xhr = newRequest({
xdomain: false,
});
return xhr && xhr.responseType !== null;
})();
/**
* HTTP long-polling based on the built-in `XMLHttpRequest` object.
*
* Usage: browser
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
export class XHR extends BaseXHR {
constructor(opts) {
super(opts);
const forceBase64 = opts && opts.forceBase64;
this.supportsBinary = hasXHR2 && !forceBase64;
}
request(opts = {}) {
Object.assign(opts, { xd: this.xd }, this.opts);
return new Request(newRequest, this.uri(), opts);
}
}
function newRequest(opts) {
const xdomain = opts.xdomain;
// XMLHttpRequest can be disabled on IE
try {
if ("undefined" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
return new XMLHttpRequest();
}
}
catch (e) { }
if (!xdomain) {
try {
return new globalThis[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
}
catch (e) { }
}
}

View File

@ -0,0 +1,11 @@
import { BaseXHR, Request } from "./polling-xhr.js";
/**
* HTTP long-polling based on the `XMLHttpRequest` object provided by the `xmlhttprequest-ssl` package.
*
* Usage: Node.js, Deno (compat), Bun (compat)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
export declare class XHR extends BaseXHR {
request(opts?: Record<string, any>): Request;
}

View File

@ -0,0 +1,17 @@
import * as XMLHttpRequestModule from "xmlhttprequest-ssl";
import { BaseXHR, Request } from "./polling-xhr.js";
const XMLHttpRequest = XMLHttpRequestModule.default || XMLHttpRequestModule;
/**
* HTTP long-polling based on the `XMLHttpRequest` object provided by the `xmlhttprequest-ssl` package.
*
* Usage: Node.js, Deno (compat), Bun (compat)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
export class XHR extends BaseXHR {
request(opts = {}) {
var _a;
Object.assign(opts, { xd: this.xd, cookieJar: (_a = this.socket) === null || _a === void 0 ? void 0 : _a._cookieJar }, this.opts);
return new Request((opts) => new XMLHttpRequest(opts), this.uri(), opts);
}
}

View File

@ -0,0 +1,52 @@
import { Transport } from "../transport.js";
export declare abstract class Polling extends Transport {
private _polling;
get name(): string;
/**
* Opens the socket (triggers polling). We write a PING message to determine
* when the transport is open.
*
* @protected
*/
doOpen(): void;
/**
* Pauses polling.
*
* @param {Function} onPause - callback upon buffers are flushed and transport is paused
* @package
*/
pause(onPause: any): void;
/**
* Starts polling cycle.
*
* @private
*/
private _poll;
/**
* Overloads onData to detect payloads.
*
* @protected
*/
onData(data: any): void;
/**
* For polling, send a close packet.
*
* @protected
*/
doClose(): void;
/**
* Writes a packets payload.
*
* @param {Array} packets - data packets
* @protected
*/
write(packets: any): void;
/**
* Generates uri for connection.
*
* @private
*/
protected uri(): string;
abstract doPoll(): any;
abstract doWrite(data: string, callback: () => void): any;
}

View File

@ -0,0 +1,158 @@
import { Transport } from "../transport.js";
import { randomString } from "../util.js";
import { encodePayload, decodePayload } from "engine.io-parser";
import debugModule from "debug"; // debug()
const debug = debugModule("engine.io-client:polling"); // debug()
export class Polling extends Transport {
constructor() {
super(...arguments);
this._polling = false;
}
get name() {
return "polling";
}
/**
* Opens the socket (triggers polling). We write a PING message to determine
* when the transport is open.
*
* @protected
*/
doOpen() {
this._poll();
}
/**
* Pauses polling.
*
* @param {Function} onPause - callback upon buffers are flushed and transport is paused
* @package
*/
pause(onPause) {
this.readyState = "pausing";
const pause = () => {
debug("paused");
this.readyState = "paused";
onPause();
};
if (this._polling || !this.writable) {
let total = 0;
if (this._polling) {
debug("we are currently polling - waiting to pause");
total++;
this.once("pollComplete", function () {
debug("pre-pause polling complete");
--total || pause();
});
}
if (!this.writable) {
debug("we are currently writing - waiting to pause");
total++;
this.once("drain", function () {
debug("pre-pause writing complete");
--total || pause();
});
}
}
else {
pause();
}
}
/**
* Starts polling cycle.
*
* @private
*/
_poll() {
debug("polling");
this._polling = true;
this.doPoll();
this.emitReserved("poll");
}
/**
* Overloads onData to detect payloads.
*
* @protected
*/
onData(data) {
debug("polling got data %s", data);
const callback = (packet) => {
// if its the first message we consider the transport open
if ("opening" === this.readyState && packet.type === "open") {
this.onOpen();
}
// if its a close packet, we close the ongoing requests
if ("close" === packet.type) {
this.onClose({ description: "transport closed by the server" });
return false;
}
// otherwise bypass onData and handle the message
this.onPacket(packet);
};
// decode payload
decodePayload(data, this.socket.binaryType).forEach(callback);
// if an event did not trigger closing
if ("closed" !== this.readyState) {
// if we got data we're not polling
this._polling = false;
this.emitReserved("pollComplete");
if ("open" === this.readyState) {
this._poll();
}
else {
debug('ignoring poll - transport state "%s"', this.readyState);
}
}
}
/**
* For polling, send a close packet.
*
* @protected
*/
doClose() {
const close = () => {
debug("writing close packet");
this.write([{ type: "close" }]);
};
if ("open" === this.readyState) {
debug("transport open - closing");
close();
}
else {
// in case we're trying to close while
// handshaking is in progress (GH-164)
debug("transport not open - deferring close");
this.once("open", close);
}
}
/**
* Writes a packets payload.
*
* @param {Array} packets - data packets
* @protected
*/
write(packets) {
this.writable = false;
encodePayload(packets, (data) => {
this.doWrite(data, () => {
this.writable = true;
this.emitReserved("drain");
});
});
}
/**
* Generates uri for connection.
*
* @private
*/
uri() {
const schema = this.opts.secure ? "https" : "http";
const query = this.query || {};
// cache busting is forced
if (false !== this.opts.timestampRequests) {
query[this.opts.timestampParam] = randomString();
}
if (!this.supportsBinary && !query.sid) {
query.b64 = 1;
}
return this.createUri(schema, query);
}
}

View File

@ -0,0 +1,36 @@
import { Transport } from "../transport.js";
import type { Packet, RawData } from "engine.io-parser";
export declare abstract class BaseWS extends Transport {
protected ws: any;
get name(): string;
doOpen(): this;
abstract createSocket(uri: string, protocols: string | string[] | undefined, opts: Record<string, any>): any;
/**
* Adds event listeners to the socket
*
* @private
*/
private addEventListeners;
write(packets: any): void;
abstract doWrite(packet: Packet, data: RawData): any;
doClose(): void;
/**
* Generates uri for connection.
*
* @private
*/
private uri;
}
/**
* WebSocket transport based on the built-in `WebSocket` object.
*
* Usage: browser, Node.js (since v21), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* @see https://caniuse.com/mdn-api_websocket
* @see https://nodejs.org/api/globals.html#websocket
*/
export declare class WS extends BaseWS {
createSocket(uri: string, protocols: string | string[] | undefined, opts: Record<string, any>): any;
doWrite(_packet: Packet, data: RawData): void;
}

View File

@ -0,0 +1,128 @@
import { Transport } from "../transport.js";
import { pick, randomString } from "../util.js";
import { encodePacket } from "engine.io-parser";
import { globalThisShim as globalThis, nextTick } from "../globals.node.js";
import debugModule from "debug"; // debug()
const debug = debugModule("engine.io-client:websocket"); // debug()
// detect ReactNative environment
const isReactNative = typeof navigator !== "undefined" &&
typeof navigator.product === "string" &&
navigator.product.toLowerCase() === "reactnative";
export class BaseWS extends Transport {
get name() {
return "websocket";
}
doOpen() {
const uri = this.uri();
const protocols = this.opts.protocols;
// React Native only supports the 'headers' option, and will print a warning if anything else is passed
const opts = isReactNative
? {}
: pick(this.opts, "agent", "perMessageDeflate", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "localAddress", "protocolVersion", "origin", "maxPayload", "family", "checkServerIdentity");
if (this.opts.extraHeaders) {
opts.headers = this.opts.extraHeaders;
}
try {
this.ws = this.createSocket(uri, protocols, opts);
}
catch (err) {
return this.emitReserved("error", err);
}
this.ws.binaryType = this.socket.binaryType;
this.addEventListeners();
}
/**
* Adds event listeners to the socket
*
* @private
*/
addEventListeners() {
this.ws.onopen = () => {
if (this.opts.autoUnref) {
this.ws._socket.unref();
}
this.onOpen();
};
this.ws.onclose = (closeEvent) => this.onClose({
description: "websocket connection closed",
context: closeEvent,
});
this.ws.onmessage = (ev) => this.onData(ev.data);
this.ws.onerror = (e) => this.onError("websocket error", e);
}
write(packets) {
this.writable = false;
// encodePacket efficient as it uses WS framing
// no need for encodePayload
for (let i = 0; i < packets.length; i++) {
const packet = packets[i];
const lastPacket = i === packets.length - 1;
encodePacket(packet, this.supportsBinary, (data) => {
// Sometimes the websocket has already been closed but the browser didn't
// have a chance of informing us about it yet, in that case send will
// throw an error
try {
this.doWrite(packet, data);
}
catch (e) {
debug("websocket closed before onclose event");
}
if (lastPacket) {
// fake drain
// defer to next tick to allow Socket to clear writeBuffer
nextTick(() => {
this.writable = true;
this.emitReserved("drain");
}, this.setTimeoutFn);
}
});
}
}
doClose() {
if (typeof this.ws !== "undefined") {
this.ws.onerror = () => { };
this.ws.close();
this.ws = null;
}
}
/**
* Generates uri for connection.
*
* @private
*/
uri() {
const schema = this.opts.secure ? "wss" : "ws";
const query = this.query || {};
// append timestamp to URI
if (this.opts.timestampRequests) {
query[this.opts.timestampParam] = randomString();
}
// communicate binary support capabilities
if (!this.supportsBinary) {
query.b64 = 1;
}
return this.createUri(schema, query);
}
}
const WebSocketCtor = globalThis.WebSocket || globalThis.MozWebSocket;
/**
* WebSocket transport based on the built-in `WebSocket` object.
*
* Usage: browser, Node.js (since v21), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* @see https://caniuse.com/mdn-api_websocket
* @see https://nodejs.org/api/globals.html#websocket
*/
export class WS extends BaseWS {
createSocket(uri, protocols, opts) {
return !isReactNative
? protocols
? new WebSocketCtor(uri, protocols)
: new WebSocketCtor(uri)
: new WebSocketCtor(uri, protocols, opts);
}
doWrite(_packet, data) {
this.ws.send(data);
}
}

View File

@ -0,0 +1,14 @@
import type { Packet, RawData } from "engine.io-parser";
import { BaseWS } from "./websocket.js";
/**
* WebSocket transport based on the `WebSocket` object provided by the `ws` package.
*
* Usage: Node.js, Deno (compat), Bun (compat)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* @see https://caniuse.com/mdn-api_websocket
*/
export declare class WS extends BaseWS {
createSocket(uri: string, protocols: string | string[] | undefined, opts: Record<string, any>): any;
doWrite(packet: Packet, data: RawData): void;
}

View File

@ -0,0 +1,41 @@
import { WebSocket } from "ws";
import { BaseWS } from "./websocket.js";
/**
* WebSocket transport based on the `WebSocket` object provided by the `ws` package.
*
* Usage: Node.js, Deno (compat), Bun (compat)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* @see https://caniuse.com/mdn-api_websocket
*/
export class WS extends BaseWS {
createSocket(uri, protocols, opts) {
var _a;
if ((_a = this.socket) === null || _a === void 0 ? void 0 : _a._cookieJar) {
opts.headers = opts.headers || {};
opts.headers.cookie =
typeof opts.headers.cookie === "string"
? [opts.headers.cookie]
: opts.headers.cookie || [];
for (const [name, cookie] of this.socket._cookieJar.cookies) {
opts.headers.cookie.push(`${name}=${cookie.value}`);
}
}
return new WebSocket(uri, protocols, opts);
}
doWrite(packet, data) {
const opts = {};
if (packet.options) {
opts.compress = packet.options.compress;
}
if (this.opts.perMessageDeflate) {
const len =
// @ts-ignore
"string" === typeof data ? Buffer.byteLength(data) : data.length;
if (len < this.opts.perMessageDeflate.threshold) {
opts.compress = false;
}
}
this.ws.send(data, opts);
}
}

View File

@ -0,0 +1,18 @@
import { Transport } from "../transport.js";
import { Packet } from "engine.io-parser";
/**
* WebTransport transport based on the built-in `WebTransport` object.
*
* Usage: browser, Node.js (with the `@fails-components/webtransport` package)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport
* @see https://caniuse.com/webtransport
*/
export declare class WT extends Transport {
private _transport;
private _writer;
get name(): string;
protected doOpen(): this;
protected write(packets: Packet[]): void;
protected doClose(): void;
}

View File

@ -0,0 +1,87 @@
import { Transport } from "../transport.js";
import { nextTick } from "../globals.node.js";
import { createPacketDecoderStream, createPacketEncoderStream, } from "engine.io-parser";
import debugModule from "debug"; // debug()
const debug = debugModule("engine.io-client:webtransport"); // debug()
/**
* WebTransport transport based on the built-in `WebTransport` object.
*
* Usage: browser, Node.js (with the `@fails-components/webtransport` package)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport
* @see https://caniuse.com/webtransport
*/
export class WT extends Transport {
get name() {
return "webtransport";
}
doOpen() {
try {
// @ts-ignore
this._transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
}
catch (err) {
return this.emitReserved("error", err);
}
this._transport.closed
.then(() => {
debug("transport closed gracefully");
this.onClose();
})
.catch((err) => {
debug("transport closed due to %s", err);
this.onError("webtransport error", err);
});
// note: we could have used async/await, but that would require some additional polyfills
this._transport.ready.then(() => {
this._transport.createBidirectionalStream().then((stream) => {
const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
const reader = stream.readable.pipeThrough(decoderStream).getReader();
const encoderStream = createPacketEncoderStream();
encoderStream.readable.pipeTo(stream.writable);
this._writer = encoderStream.writable.getWriter();
const read = () => {
reader
.read()
.then(({ done, value }) => {
if (done) {
debug("session is closed");
return;
}
debug("received chunk: %o", value);
this.onPacket(value);
read();
})
.catch((err) => {
debug("an error occurred while reading: %s", err);
});
};
read();
const packet = { type: "open" };
if (this.query.sid) {
packet.data = `{"sid":"${this.query.sid}"}`;
}
this._writer.write(packet).then(() => this.onOpen());
});
});
}
write(packets) {
this.writable = false;
for (let i = 0; i < packets.length; i++) {
const packet = packets[i];
const lastPacket = i === packets.length - 1;
this._writer.write(packet).then(() => {
if (lastPacket) {
nextTick(() => {
this.writable = true;
this.emitReserved("drain");
}, this.setTimeoutFn);
}
});
}
}
doClose() {
var _a;
(_a = this._transport) === null || _a === void 0 ? void 0 : _a.close();
}
}

View File

@ -0,0 +1,7 @@
export declare function pick(obj: any, ...attr: any[]): any;
export declare function installTimerFunctions(obj: any, opts: any): void;
export declare function byteLength(obj: any): number;
/**
* Generates a random 8-characters string.
*/
export declare function randomString(): string;

59
node_modules/engine.io-client/build/esm-debug/util.js generated vendored Normal file
View File

@ -0,0 +1,59 @@
import { globalThisShim as globalThis } from "./globals.node.js";
export function pick(obj, ...attr) {
return attr.reduce((acc, k) => {
if (obj.hasOwnProperty(k)) {
acc[k] = obj[k];
}
return acc;
}, {});
}
// Keep a reference to the real timeout functions so they can be used when overridden
const NATIVE_SET_TIMEOUT = globalThis.setTimeout;
const NATIVE_CLEAR_TIMEOUT = globalThis.clearTimeout;
export function installTimerFunctions(obj, opts) {
if (opts.useNativeTimers) {
obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThis);
obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThis);
}
else {
obj.setTimeoutFn = globalThis.setTimeout.bind(globalThis);
obj.clearTimeoutFn = globalThis.clearTimeout.bind(globalThis);
}
}
// base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)
const BASE64_OVERHEAD = 1.33;
// we could also have used `new Blob([obj]).size`, but it isn't supported in IE9
export function byteLength(obj) {
if (typeof obj === "string") {
return utf8Length(obj);
}
// arraybuffer or blob
return Math.ceil((obj.byteLength || obj.size) * BASE64_OVERHEAD);
}
function utf8Length(str) {
let c = 0, length = 0;
for (let i = 0, l = str.length; i < l; i++) {
c = str.charCodeAt(i);
if (c < 0x80) {
length += 1;
}
else if (c < 0x800) {
length += 2;
}
else if (c < 0xd800 || c >= 0xe000) {
length += 3;
}
else {
i++;
length += 4;
}
}
return length;
}
/**
* Generates a random 8-characters string.
*/
export function randomString() {
return (Date.now().toString(36).substring(3) +
Math.random().toString(36).substring(2, 5));
}

View File

@ -0,0 +1,3 @@
import { Socket } from "./socket.js";
declare const _default: (uri: any, opts: any) => Socket;
export default _default;

View File

@ -0,0 +1,2 @@
import { Socket } from "./socket.js";
export default (uri, opts) => new Socket(uri, opts);

View File

@ -0,0 +1 @@
export declare const hasCORS: boolean;

View File

@ -0,0 +1,11 @@
// imported from https://github.com/component/has-cors
let value = false;
try {
value = typeof XMLHttpRequest !== 'undefined' &&
'withCredentials' in new XMLHttpRequest();
}
catch (err) {
// if XMLHttp support is disabled in IE then it will throw
// when trying to create
}
export const hasCORS = value;

View File

@ -0,0 +1,15 @@
/**
* Compiles a querystring
* Returns string representation of the object
*
* @param {Object}
* @api private
*/
export declare function encode(obj: any): string;
/**
* Parses a simple querystring into an object
*
* @param {String} qs
* @api private
*/
export declare function decode(qs: any): {};

View File

@ -0,0 +1,34 @@
// imported from https://github.com/galkn/querystring
/**
* Compiles a querystring
* Returns string representation of the object
*
* @param {Object}
* @api private
*/
export function encode(obj) {
let str = '';
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
if (str.length)
str += '&';
str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
}
}
return str;
}
/**
* Parses a simple querystring into an object
*
* @param {String} qs
* @api private
*/
export function decode(qs) {
let qry = {};
let pairs = qs.split('&');
for (let i = 0, l = pairs.length; i < l; i++) {
let pair = pairs[i].split('=');
qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
return qry;
}

View File

@ -0,0 +1 @@
export declare function parse(str: string): any;

View File

@ -0,0 +1,64 @@
// imported from https://github.com/galkn/parseuri
/**
* Parses a URI
*
* Note: we could also have used the built-in URL object, but it isn't supported on all platforms.
*
* See:
* - https://developer.mozilla.org/en-US/docs/Web/API/URL
* - https://caniuse.com/url
* - https://www.rfc-editor.org/rfc/rfc3986#appendix-B
*
* History of the parse() method:
* - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c
* - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3
* - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242
*
* @author Steven Levithan <stevenlevithan.com> (MIT license)
* @api private
*/
const re = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
const parts = [
'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
];
export function parse(str) {
if (str.length > 8000) {
throw "URI too long";
}
const src = str, b = str.indexOf('['), e = str.indexOf(']');
if (b != -1 && e != -1) {
str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
}
let m = re.exec(str || ''), uri = {}, i = 14;
while (i--) {
uri[parts[i]] = m[i] || '';
}
if (b != -1 && e != -1) {
uri.source = src;
uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
uri.ipv6uri = true;
}
uri.pathNames = pathNames(uri, uri['path']);
uri.queryKey = queryKey(uri, uri['query']);
return uri;
}
function pathNames(obj, path) {
const regx = /\/{2,9}/g, names = path.replace(regx, "/").split("/");
if (path.slice(0, 1) == '/' || path.length === 0) {
names.splice(0, 1);
}
if (path.slice(-1) == '/') {
names.splice(names.length - 1, 1);
}
return names;
}
function queryKey(uri, query) {
const data = {};
query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {
if ($1) {
data[$1] = $2;
}
});
return data;
}

4
node_modules/engine.io-client/build/esm/globals.d.ts generated vendored Normal file
View File

@ -0,0 +1,4 @@
export declare const nextTick: (cb: any, setTimeoutFn: any) => any;
export declare const globalThisShim: any;
export declare const defaultBinaryType = "arraybuffer";
export declare function createCookieJar(): void;

22
node_modules/engine.io-client/build/esm/globals.js generated vendored Normal file
View File

@ -0,0 +1,22 @@
export const nextTick = (() => {
const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
if (isPromiseAvailable) {
return (cb) => Promise.resolve().then(cb);
}
else {
return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
}
})();
export const globalThisShim = (() => {
if (typeof self !== "undefined") {
return self;
}
else if (typeof window !== "undefined") {
return window;
}
else {
return Function("return this")();
}
})();
export const defaultBinaryType = "arraybuffer";
export function createCookieJar() { }

View File

@ -0,0 +1,21 @@
export declare const nextTick: (callback: Function, ...args: any[]) => void;
export declare const globalThisShim: typeof globalThis;
export declare const defaultBinaryType = "nodebuffer";
export declare function createCookieJar(): CookieJar;
interface Cookie {
name: string;
value: string;
expires?: Date;
}
/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
*/
export declare function parse(setCookieString: string): Cookie;
export declare class CookieJar {
private _cookies;
parseCookies(values: string[]): void;
get cookies(): IterableIterator<[string, Cookie]>;
addCookies(xhr: any): void;
appendCookies(headers: Headers): void;
}
export {};

View File

@ -0,0 +1,91 @@
export const nextTick = process.nextTick;
export const globalThisShim = global;
export const defaultBinaryType = "nodebuffer";
export function createCookieJar() {
return new CookieJar();
}
/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
*/
export function parse(setCookieString) {
const parts = setCookieString.split("; ");
const i = parts[0].indexOf("=");
if (i === -1) {
return;
}
const name = parts[0].substring(0, i).trim();
if (!name.length) {
return;
}
let value = parts[0].substring(i + 1).trim();
if (value.charCodeAt(0) === 0x22) {
// remove double quotes
value = value.slice(1, -1);
}
const cookie = {
name,
value,
};
for (let j = 1; j < parts.length; j++) {
const subParts = parts[j].split("=");
if (subParts.length !== 2) {
continue;
}
const key = subParts[0].trim();
const value = subParts[1].trim();
switch (key) {
case "Expires":
cookie.expires = new Date(value);
break;
case "Max-Age":
const expiration = new Date();
expiration.setUTCSeconds(expiration.getUTCSeconds() + parseInt(value, 10));
cookie.expires = expiration;
break;
default:
// ignore other keys
}
}
return cookie;
}
export class CookieJar {
constructor() {
this._cookies = new Map();
}
parseCookies(values) {
if (!values) {
return;
}
values.forEach((value) => {
const parsed = parse(value);
if (parsed) {
this._cookies.set(parsed.name, parsed);
}
});
}
get cookies() {
const now = Date.now();
this._cookies.forEach((cookie, name) => {
var _a;
if (((_a = cookie.expires) === null || _a === void 0 ? void 0 : _a.getTime()) < now) {
this._cookies.delete(name);
}
});
return this._cookies.entries();
}
addCookies(xhr) {
const cookies = [];
for (const [name, cookie] of this.cookies) {
cookies.push(`${name}=${cookie.value}`);
}
if (cookies.length) {
xhr.setDisableHeaderCheck(true);
xhr.setRequestHeader("cookie", cookies.join("; "));
}
}
appendCookies(headers) {
for (const [name, cookie] of this.cookies) {
headers.append("cookie", `${name}=${cookie.value}`);
}
}
}

15
node_modules/engine.io-client/build/esm/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,15 @@
import { Socket } from "./socket.js";
export { Socket };
export { SocketOptions, SocketWithoutUpgrade, SocketWithUpgrade, } from "./socket.js";
export declare const protocol: number;
export { Transport, TransportError } from "./transport.js";
export { transports } from "./transports/index.js";
export { installTimerFunctions } from "./util.js";
export { parse } from "./contrib/parseuri.js";
export { nextTick } from "./globals.node.js";
export { Fetch } from "./transports/polling-fetch.js";
export { XHR as NodeXHR } from "./transports/polling-xhr.node.js";
export { XHR } from "./transports/polling-xhr.js";
export { WS as NodeWebSocket } from "./transports/websocket.node.js";
export { WS as WebSocket } from "./transports/websocket.js";
export { WT as WebTransport } from "./transports/webtransport.js";

15
node_modules/engine.io-client/build/esm/index.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
import { Socket } from "./socket.js";
export { Socket };
export { SocketWithoutUpgrade, SocketWithUpgrade, } from "./socket.js";
export const protocol = Socket.protocol;
export { Transport, TransportError } from "./transport.js";
export { transports } from "./transports/index.js";
export { installTimerFunctions } from "./util.js";
export { parse } from "./contrib/parseuri.js";
export { nextTick } from "./globals.node.js";
export { Fetch } from "./transports/polling-fetch.js";
export { XHR as NodeXHR } from "./transports/polling-xhr.node.js";
export { XHR } from "./transports/polling-xhr.js";
export { WS as NodeWebSocket } from "./transports/websocket.node.js";
export { WS as WebSocket } from "./transports/websocket.js";
export { WT as WebTransport } from "./transports/webtransport.js";

10
node_modules/engine.io-client/build/esm/package.json generated vendored Normal file
View File

@ -0,0 +1,10 @@
{
"name": "engine.io-client",
"type": "module",
"browser": {
"ws": false,
"./transports/polling-xhr.node.js": "./transports/polling-xhr.js",
"./transports/websocket.node.js": "./transports/websocket.js",
"./globals.node.js": "./globals.js"
}
}

482
node_modules/engine.io-client/build/esm/socket.d.ts generated vendored Normal file
View File

@ -0,0 +1,482 @@
import { Emitter } from "@socket.io/component-emitter";
import type { Packet, BinaryType, RawData } from "engine.io-parser";
import { CloseDetails, Transport } from "./transport.js";
import { CookieJar } from "./globals.node.js";
export interface SocketOptions {
/**
* The host that we're connecting to. Set from the URI passed when connecting
*/
host?: string;
/**
* The hostname for our connection. Set from the URI passed when connecting
*/
hostname?: string;
/**
* If this is a secure connection. Set from the URI passed when connecting
*/
secure?: boolean;
/**
* The port for our connection. Set from the URI passed when connecting
*/
port?: string | number;
/**
* Any query parameters in our uri. Set from the URI passed when connecting
*/
query?: {
[key: string]: any;
};
/**
* `http.Agent` to use, defaults to `false` (NodeJS only)
*
* Note: the type should be "undefined | http.Agent | https.Agent | false", but this would break browser-only clients.
*
* @see https://nodejs.org/api/http.html#httprequestoptions-callback
*/
agent?: string | boolean;
/**
* Whether the client should try to upgrade the transport from
* long-polling to something better.
* @default true
*/
upgrade?: boolean;
/**
* Forces base 64 encoding for polling transport even when XHR2
* responseType is available and WebSocket even if the used standard
* supports binary.
*/
forceBase64?: boolean;
/**
* The param name to use as our timestamp key
* @default 't'
*/
timestampParam?: string;
/**
* Whether to add the timestamp with each transport request. Note: this
* is ignored if the browser is IE or Android, in which case requests
* are always stamped
* @default false
*/
timestampRequests?: boolean;
/**
* A list of transports to try (in order). Engine.io always attempts to
* connect directly with the first one, provided the feature detection test
* for it passes.
*
* @default ['polling','websocket', 'webtransport']
*/
transports?: ("polling" | "websocket" | "webtransport" | string)[] | TransportCtor[];
/**
* Whether all the transports should be tested, instead of just the first one.
*
* If set to `true`, the client will first try to connect with HTTP long-polling, and then with WebSocket in case of
* failure, and finally with WebTransport if the previous attempts have failed.
*
* If set to `false` (default), if the connection with HTTP long-polling fails, then the client will not test the
* other transports and will abort the connection.
*
* @default false
*/
tryAllTransports?: boolean;
/**
* If true and if the previous websocket connection to the server succeeded,
* the connection attempt will bypass the normal upgrade process and will
* initially try websocket. A connection attempt following a transport error
* will use the normal upgrade process. It is recommended you turn this on
* only when using SSL/TLS connections, or if you know that your network does
* not block websockets.
* @default false
*/
rememberUpgrade?: boolean;
/**
* Timeout for xhr-polling requests in milliseconds (0) (only for polling transport)
*/
requestTimeout?: number;
/**
* Transport options for Node.js client (headers etc)
*/
transportOptions?: Object;
/**
* (SSL) Certificate, Private key and CA certificates to use for SSL.
* Can be used in Node.js client environment to manually specify
* certificate information.
*/
pfx?: string;
/**
* (SSL) Private key to use for SSL. Can be used in Node.js client
* environment to manually specify certificate information.
*/
key?: string;
/**
* (SSL) A string or passphrase for the private key or pfx. Can be
* used in Node.js client environment to manually specify certificate
* information.
*/
passphrase?: string;
/**
* (SSL) Public x509 certificate to use. Can be used in Node.js client
* environment to manually specify certificate information.
*/
cert?: string;
/**
* (SSL) An authority certificate or array of authority certificates to
* check the remote host against.. Can be used in Node.js client
* environment to manually specify certificate information.
*/
ca?: string | string[];
/**
* (SSL) A string describing the ciphers to use or exclude. Consult the
* [cipher format list]
* (http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT) for
* details on the format.. Can be used in Node.js client environment to
* manually specify certificate information.
*/
ciphers?: string;
/**
* (SSL) If true, the server certificate is verified against the list of
* supplied CAs. An 'error' event is emitted if verification fails.
* Verification happens at the connection level, before the HTTP request
* is sent. Can be used in Node.js client environment to manually specify
* certificate information.
*/
rejectUnauthorized?: boolean;
/**
* Headers that will be passed for each request to the server (via xhr-polling and via websockets).
* These values then can be used during handshake or for special proxies.
*/
extraHeaders?: {
[header: string]: string;
};
/**
* Whether to include credentials (cookies, authorization headers, TLS
* client certificates, etc.) with cross-origin XHR polling requests
* @default false
*/
withCredentials?: boolean;
/**
* Whether to automatically close the connection whenever the beforeunload event is received.
* @default false
*/
closeOnBeforeunload?: boolean;
/**
* Whether to always use the native timeouts. This allows the client to
* reconnect when the native timeout functions are overridden, such as when
* mock clocks are installed.
* @default false
*/
useNativeTimers?: boolean;
/**
* Whether the heartbeat timer should be unref'ed, in order not to keep the Node.js event loop active.
*
* @see https://nodejs.org/api/timers.html#timeoutunref
* @default false
*/
autoUnref?: boolean;
/**
* parameters of the WebSocket permessage-deflate extension (see ws module api docs). Set to false to disable.
* @default false
*/
perMessageDeflate?: {
threshold: number;
};
/**
* The path to get our client file from, in the case of the server
* serving it
* @default '/engine.io'
*/
path?: string;
/**
* Whether we should add a trailing slash to the request path.
* @default true
*/
addTrailingSlash?: boolean;
/**
* Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols,
* so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to
* be able to handle different types of interactions depending on the specified protocol)
* @default []
*/
protocols?: string | string[];
}
type TransportCtor = {
new (o: any): Transport;
};
type BaseSocketOptions = Omit<SocketOptions, "transports"> & {
transports: TransportCtor[];
};
interface HandshakeData {
sid: string;
upgrades: string[];
pingInterval: number;
pingTimeout: number;
maxPayload: number;
}
interface SocketReservedEvents {
open: () => void;
handshake: (data: HandshakeData) => void;
packet: (packet: Packet) => void;
packetCreate: (packet: Packet) => void;
data: (data: RawData) => void;
message: (data: RawData) => void;
drain: () => void;
flush: () => void;
heartbeat: () => void;
ping: () => void;
pong: () => void;
error: (err: string | Error) => void;
upgrading: (transport: Transport) => void;
upgrade: (transport: Transport) => void;
upgradeError: (err: Error) => void;
close: (reason: string, description?: CloseDetails | Error) => void;
}
type SocketState = "opening" | "open" | "closing" | "closed";
interface WriteOptions {
compress?: boolean;
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes without upgrade mechanism, which means that it will keep the first low-level transport that
* successfully establishes the connection.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithoutUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithUpgrade
* @see Socket
*/
export declare class SocketWithoutUpgrade extends Emitter<Record<never, never>, Record<never, never>, SocketReservedEvents> {
id: string;
transport: Transport;
binaryType: BinaryType;
readyState: SocketState;
writeBuffer: Packet[];
protected readonly opts: BaseSocketOptions;
protected readonly transports: string[];
protected upgrading: boolean;
protected setTimeoutFn: typeof setTimeout;
private _prevBufferLen;
private _pingInterval;
private _pingTimeout;
private _maxPayload?;
private _pingTimeoutTimer;
/**
* The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
* callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
*/
private _pingTimeoutTime;
private clearTimeoutFn;
private readonly _beforeunloadEventListener;
private readonly _offlineEventListener;
private readonly secure;
private readonly hostname;
private readonly port;
private readonly _transportsByName;
/**
* The cookie jar will store the cookies sent by the server (Node. js only).
*/
readonly _cookieJar: CookieJar;
static priorWebsocketSuccess: boolean;
static protocol: number;
/**
* Socket constructor.
*
* @param {String|Object} uri - uri or options
* @param {Object} opts - options
*/
constructor(uri: string | BaseSocketOptions, opts: BaseSocketOptions);
/**
* Creates transport of the given type.
*
* @param {String} name - transport name
* @return {Transport}
* @private
*/
protected createTransport(name: string): Transport;
/**
* Initializes transport to use and starts probe.
*
* @private
*/
private _open;
/**
* Sets the current transport. Disables the existing one (if any).
*
* @private
*/
protected setTransport(transport: Transport): void;
/**
* Called when connection is deemed open.
*
* @private
*/
protected onOpen(): void;
/**
* Handles a packet.
*
* @private
*/
private _onPacket;
/**
* Called upon handshake completion.
*
* @param {Object} data - handshake obj
* @private
*/
protected onHandshake(data: HandshakeData): void;
/**
* Sets and resets ping timeout timer based on server pings.
*
* @private
*/
private _resetPingTimeout;
/**
* Called on `drain` event
*
* @private
*/
private _onDrain;
/**
* Flush write buffers.
*
* @private
*/
protected flush(): void;
/**
* Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
* long-polling)
*
* @private
*/
private _getWritablePackets;
/**
* Checks whether the heartbeat timer has expired but the socket has not yet been notified.
*
* Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
* `write()` method then the message would not be buffered by the Socket.IO client.
*
* @return {boolean}
* @private
*/
_hasPingExpired(): boolean;
/**
* Sends a message.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
write(msg: RawData, options?: WriteOptions, fn?: () => void): this;
/**
* Sends a message. Alias of {@link Socket#write}.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
send(msg: RawData, options?: WriteOptions, fn?: () => void): this;
/**
* Sends a packet.
*
* @param {String} type: packet type.
* @param {String} data.
* @param {Object} options.
* @param {Function} fn - callback function.
* @private
*/
private _sendPacket;
/**
* Closes the connection.
*/
close(): this;
/**
* Called upon transport error
*
* @private
*/
private _onError;
/**
* Called upon transport close.
*
* @private
*/
private _onClose;
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see Socket
*/
export declare class SocketWithUpgrade extends SocketWithoutUpgrade {
private _upgrades;
onOpen(): void;
/**
* Probes a transport.
*
* @param {String} name - transport name
* @private
*/
private _probe;
onHandshake(data: HandshakeData): void;
/**
* Filters upgrades, returning only those matching client transports.
*
* @param {Array} upgrades - server upgrades
* @private
*/
private _filterUpgrades;
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* @example
* import { Socket } from "engine.io-client";
*
* const socket = new Socket();
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see SocketWithUpgrade
*/
export declare class Socket extends SocketWithUpgrade {
constructor(uri?: string, opts?: SocketOptions);
constructor(opts: SocketOptions);
}
export {};

727
node_modules/engine.io-client/build/esm/socket.js generated vendored Normal file
View File

@ -0,0 +1,727 @@
import { transports as DEFAULT_TRANSPORTS } from "./transports/index.js";
import { installTimerFunctions, byteLength } from "./util.js";
import { decode } from "./contrib/parseqs.js";
import { parse } from "./contrib/parseuri.js";
import { Emitter } from "@socket.io/component-emitter";
import { protocol } from "engine.io-parser";
import { createCookieJar, defaultBinaryType, nextTick, } from "./globals.node.js";
const withEventListeners = typeof addEventListener === "function" &&
typeof removeEventListener === "function";
const OFFLINE_EVENT_LISTENERS = [];
if (withEventListeners) {
// within a ServiceWorker, any event handler for the 'offline' event must be added on the initial evaluation of the
// script, so we create one single event listener here which will forward the event to the socket instances
addEventListener("offline", () => {
OFFLINE_EVENT_LISTENERS.forEach((listener) => listener());
}, false);
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes without upgrade mechanism, which means that it will keep the first low-level transport that
* successfully establishes the connection.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithoutUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithUpgrade
* @see Socket
*/
export class SocketWithoutUpgrade extends Emitter {
/**
* Socket constructor.
*
* @param {String|Object} uri - uri or options
* @param {Object} opts - options
*/
constructor(uri, opts) {
super();
this.binaryType = defaultBinaryType;
this.writeBuffer = [];
this._prevBufferLen = 0;
this._pingInterval = -1;
this._pingTimeout = -1;
this._maxPayload = -1;
/**
* The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
* callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
*/
this._pingTimeoutTime = Infinity;
if (uri && "object" === typeof uri) {
opts = uri;
uri = null;
}
if (uri) {
const parsedUri = parse(uri);
opts.hostname = parsedUri.host;
opts.secure =
parsedUri.protocol === "https" || parsedUri.protocol === "wss";
opts.port = parsedUri.port;
if (parsedUri.query)
opts.query = parsedUri.query;
}
else if (opts.host) {
opts.hostname = parse(opts.host).host;
}
installTimerFunctions(this, opts);
this.secure =
null != opts.secure
? opts.secure
: typeof location !== "undefined" && "https:" === location.protocol;
if (opts.hostname && !opts.port) {
// if no port is specified manually, use the protocol default
opts.port = this.secure ? "443" : "80";
}
this.hostname =
opts.hostname ||
(typeof location !== "undefined" ? location.hostname : "localhost");
this.port =
opts.port ||
(typeof location !== "undefined" && location.port
? location.port
: this.secure
? "443"
: "80");
this.transports = [];
this._transportsByName = {};
opts.transports.forEach((t) => {
const transportName = t.prototype.name;
this.transports.push(transportName);
this._transportsByName[transportName] = t;
});
this.opts = Object.assign({
path: "/engine.io",
agent: false,
withCredentials: false,
upgrade: true,
timestampParam: "t",
rememberUpgrade: false,
addTrailingSlash: true,
rejectUnauthorized: true,
perMessageDeflate: {
threshold: 1024,
},
transportOptions: {},
closeOnBeforeunload: false,
}, opts);
this.opts.path =
this.opts.path.replace(/\/$/, "") +
(this.opts.addTrailingSlash ? "/" : "");
if (typeof this.opts.query === "string") {
this.opts.query = decode(this.opts.query);
}
if (withEventListeners) {
if (this.opts.closeOnBeforeunload) {
// Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
// ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
// closed/reloaded)
this._beforeunloadEventListener = () => {
if (this.transport) {
// silently close the transport
this.transport.removeAllListeners();
this.transport.close();
}
};
addEventListener("beforeunload", this._beforeunloadEventListener, false);
}
if (this.hostname !== "localhost") {
this._offlineEventListener = () => {
this._onClose("transport close", {
description: "network connection lost",
});
};
OFFLINE_EVENT_LISTENERS.push(this._offlineEventListener);
}
}
if (this.opts.withCredentials) {
this._cookieJar = createCookieJar();
}
this._open();
}
/**
* Creates transport of the given type.
*
* @param {String} name - transport name
* @return {Transport}
* @private
*/
createTransport(name) {
const query = Object.assign({}, this.opts.query);
// append engine.io protocol identifier
query.EIO = protocol;
// transport name
query.transport = name;
// session id if we already have one
if (this.id)
query.sid = this.id;
const opts = Object.assign({}, this.opts, {
query,
socket: this,
hostname: this.hostname,
secure: this.secure,
port: this.port,
}, this.opts.transportOptions[name]);
return new this._transportsByName[name](opts);
}
/**
* Initializes transport to use and starts probe.
*
* @private
*/
_open() {
if (this.transports.length === 0) {
// Emit error on next tick so it can be listened to
this.setTimeoutFn(() => {
this.emitReserved("error", "No transports available");
}, 0);
return;
}
const transportName = this.opts.rememberUpgrade &&
SocketWithoutUpgrade.priorWebsocketSuccess &&
this.transports.indexOf("websocket") !== -1
? "websocket"
: this.transports[0];
this.readyState = "opening";
const transport = this.createTransport(transportName);
transport.open();
this.setTransport(transport);
}
/**
* Sets the current transport. Disables the existing one (if any).
*
* @private
*/
setTransport(transport) {
if (this.transport) {
this.transport.removeAllListeners();
}
// set up transport
this.transport = transport;
// set up transport listeners
transport
.on("drain", this._onDrain.bind(this))
.on("packet", this._onPacket.bind(this))
.on("error", this._onError.bind(this))
.on("close", (reason) => this._onClose("transport close", reason));
}
/**
* Called when connection is deemed open.
*
* @private
*/
onOpen() {
this.readyState = "open";
SocketWithoutUpgrade.priorWebsocketSuccess =
"websocket" === this.transport.name;
this.emitReserved("open");
this.flush();
}
/**
* Handles a packet.
*
* @private
*/
_onPacket(packet) {
if ("opening" === this.readyState ||
"open" === this.readyState ||
"closing" === this.readyState) {
this.emitReserved("packet", packet);
// Socket is live - any packet counts
this.emitReserved("heartbeat");
switch (packet.type) {
case "open":
this.onHandshake(JSON.parse(packet.data));
break;
case "ping":
this._sendPacket("pong");
this.emitReserved("ping");
this.emitReserved("pong");
this._resetPingTimeout();
break;
case "error":
const err = new Error("server error");
// @ts-ignore
err.code = packet.data;
this._onError(err);
break;
case "message":
this.emitReserved("data", packet.data);
this.emitReserved("message", packet.data);
break;
}
}
else {
}
}
/**
* Called upon handshake completion.
*
* @param {Object} data - handshake obj
* @private
*/
onHandshake(data) {
this.emitReserved("handshake", data);
this.id = data.sid;
this.transport.query.sid = data.sid;
this._pingInterval = data.pingInterval;
this._pingTimeout = data.pingTimeout;
this._maxPayload = data.maxPayload;
this.onOpen();
// In case open handler closes socket
if ("closed" === this.readyState)
return;
this._resetPingTimeout();
}
/**
* Sets and resets ping timeout timer based on server pings.
*
* @private
*/
_resetPingTimeout() {
this.clearTimeoutFn(this._pingTimeoutTimer);
const delay = this._pingInterval + this._pingTimeout;
this._pingTimeoutTime = Date.now() + delay;
this._pingTimeoutTimer = this.setTimeoutFn(() => {
this._onClose("ping timeout");
}, delay);
if (this.opts.autoUnref) {
this._pingTimeoutTimer.unref();
}
}
/**
* Called on `drain` event
*
* @private
*/
_onDrain() {
this.writeBuffer.splice(0, this._prevBufferLen);
// setting prevBufferLen = 0 is very important
// for example, when upgrading, upgrade packet is sent over,
// and a nonzero prevBufferLen could cause problems on `drain`
this._prevBufferLen = 0;
if (0 === this.writeBuffer.length) {
this.emitReserved("drain");
}
else {
this.flush();
}
}
/**
* Flush write buffers.
*
* @private
*/
flush() {
if ("closed" !== this.readyState &&
this.transport.writable &&
!this.upgrading &&
this.writeBuffer.length) {
const packets = this._getWritablePackets();
this.transport.send(packets);
// keep track of current length of writeBuffer
// splice writeBuffer and callbackBuffer on `drain`
this._prevBufferLen = packets.length;
this.emitReserved("flush");
}
}
/**
* Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
* long-polling)
*
* @private
*/
_getWritablePackets() {
const shouldCheckPayloadSize = this._maxPayload &&
this.transport.name === "polling" &&
this.writeBuffer.length > 1;
if (!shouldCheckPayloadSize) {
return this.writeBuffer;
}
let payloadSize = 1; // first packet type
for (let i = 0; i < this.writeBuffer.length; i++) {
const data = this.writeBuffer[i].data;
if (data) {
payloadSize += byteLength(data);
}
if (i > 0 && payloadSize > this._maxPayload) {
return this.writeBuffer.slice(0, i);
}
payloadSize += 2; // separator + packet type
}
return this.writeBuffer;
}
/**
* Checks whether the heartbeat timer has expired but the socket has not yet been notified.
*
* Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
* `write()` method then the message would not be buffered by the Socket.IO client.
*
* @return {boolean}
* @private
*/
/* private */ _hasPingExpired() {
if (!this._pingTimeoutTime)
return true;
const hasExpired = Date.now() > this._pingTimeoutTime;
if (hasExpired) {
this._pingTimeoutTime = 0;
nextTick(() => {
this._onClose("ping timeout");
}, this.setTimeoutFn);
}
return hasExpired;
}
/**
* Sends a message.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
write(msg, options, fn) {
this._sendPacket("message", msg, options, fn);
return this;
}
/**
* Sends a message. Alias of {@link Socket#write}.
*
* @param {String} msg - message.
* @param {Object} options.
* @param {Function} fn - callback function.
* @return {Socket} for chaining.
*/
send(msg, options, fn) {
this._sendPacket("message", msg, options, fn);
return this;
}
/**
* Sends a packet.
*
* @param {String} type: packet type.
* @param {String} data.
* @param {Object} options.
* @param {Function} fn - callback function.
* @private
*/
_sendPacket(type, data, options, fn) {
if ("function" === typeof data) {
fn = data;
data = undefined;
}
if ("function" === typeof options) {
fn = options;
options = null;
}
if ("closing" === this.readyState || "closed" === this.readyState) {
return;
}
options = options || {};
options.compress = false !== options.compress;
const packet = {
type: type,
data: data,
options: options,
};
this.emitReserved("packetCreate", packet);
this.writeBuffer.push(packet);
if (fn)
this.once("flush", fn);
this.flush();
}
/**
* Closes the connection.
*/
close() {
const close = () => {
this._onClose("forced close");
this.transport.close();
};
const cleanupAndClose = () => {
this.off("upgrade", cleanupAndClose);
this.off("upgradeError", cleanupAndClose);
close();
};
const waitForUpgrade = () => {
// wait for upgrade to finish since we can't send packets while pausing a transport
this.once("upgrade", cleanupAndClose);
this.once("upgradeError", cleanupAndClose);
};
if ("opening" === this.readyState || "open" === this.readyState) {
this.readyState = "closing";
if (this.writeBuffer.length) {
this.once("drain", () => {
if (this.upgrading) {
waitForUpgrade();
}
else {
close();
}
});
}
else if (this.upgrading) {
waitForUpgrade();
}
else {
close();
}
}
return this;
}
/**
* Called upon transport error
*
* @private
*/
_onError(err) {
SocketWithoutUpgrade.priorWebsocketSuccess = false;
if (this.opts.tryAllTransports &&
this.transports.length > 1 &&
this.readyState === "opening") {
this.transports.shift();
return this._open();
}
this.emitReserved("error", err);
this._onClose("transport error", err);
}
/**
* Called upon transport close.
*
* @private
*/
_onClose(reason, description) {
if ("opening" === this.readyState ||
"open" === this.readyState ||
"closing" === this.readyState) {
// clear timers
this.clearTimeoutFn(this._pingTimeoutTimer);
// stop event from firing again for transport
this.transport.removeAllListeners("close");
// ensure transport won't stay open
this.transport.close();
// ignore further transport communication
this.transport.removeAllListeners();
if (withEventListeners) {
if (this._beforeunloadEventListener) {
removeEventListener("beforeunload", this._beforeunloadEventListener, false);
}
if (this._offlineEventListener) {
const i = OFFLINE_EVENT_LISTENERS.indexOf(this._offlineEventListener);
if (i !== -1) {
OFFLINE_EVENT_LISTENERS.splice(i, 1);
}
}
}
// set ready state
this.readyState = "closed";
// clear session id
this.id = null;
// emit close event
this.emitReserved("close", reason, description);
// clean buffers after, so users can still
// grab the buffers on `close` event
this.writeBuffer = [];
this._prevBufferLen = 0;
}
}
}
SocketWithoutUpgrade.protocol = protocol;
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
*
* @example
* import { SocketWithUpgrade, WebSocket } from "engine.io-client";
*
* const socket = new SocketWithUpgrade({
* transports: [WebSocket]
* });
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see Socket
*/
export class SocketWithUpgrade extends SocketWithoutUpgrade {
constructor() {
super(...arguments);
this._upgrades = [];
}
onOpen() {
super.onOpen();
if ("open" === this.readyState && this.opts.upgrade) {
for (let i = 0; i < this._upgrades.length; i++) {
this._probe(this._upgrades[i]);
}
}
}
/**
* Probes a transport.
*
* @param {String} name - transport name
* @private
*/
_probe(name) {
let transport = this.createTransport(name);
let failed = false;
SocketWithoutUpgrade.priorWebsocketSuccess = false;
const onTransportOpen = () => {
if (failed)
return;
transport.send([{ type: "ping", data: "probe" }]);
transport.once("packet", (msg) => {
if (failed)
return;
if ("pong" === msg.type && "probe" === msg.data) {
this.upgrading = true;
this.emitReserved("upgrading", transport);
if (!transport)
return;
SocketWithoutUpgrade.priorWebsocketSuccess =
"websocket" === transport.name;
this.transport.pause(() => {
if (failed)
return;
if ("closed" === this.readyState)
return;
cleanup();
this.setTransport(transport);
transport.send([{ type: "upgrade" }]);
this.emitReserved("upgrade", transport);
transport = null;
this.upgrading = false;
this.flush();
});
}
else {
const err = new Error("probe error");
// @ts-ignore
err.transport = transport.name;
this.emitReserved("upgradeError", err);
}
});
};
function freezeTransport() {
if (failed)
return;
// Any callback called by transport should be ignored since now
failed = true;
cleanup();
transport.close();
transport = null;
}
// Handle any error that happens while probing
const onerror = (err) => {
const error = new Error("probe error: " + err);
// @ts-ignore
error.transport = transport.name;
freezeTransport();
this.emitReserved("upgradeError", error);
};
function onTransportClose() {
onerror("transport closed");
}
// When the socket is closed while we're probing
function onclose() {
onerror("socket closed");
}
// When the socket is upgraded while we're probing
function onupgrade(to) {
if (transport && to.name !== transport.name) {
freezeTransport();
}
}
// Remove all listeners on the transport and on self
const cleanup = () => {
transport.removeListener("open", onTransportOpen);
transport.removeListener("error", onerror);
transport.removeListener("close", onTransportClose);
this.off("close", onclose);
this.off("upgrading", onupgrade);
};
transport.once("open", onTransportOpen);
transport.once("error", onerror);
transport.once("close", onTransportClose);
this.once("close", onclose);
this.once("upgrading", onupgrade);
if (this._upgrades.indexOf("webtransport") !== -1 &&
name !== "webtransport") {
// favor WebTransport
this.setTimeoutFn(() => {
if (!failed) {
transport.open();
}
}, 200);
}
else {
transport.open();
}
}
onHandshake(data) {
this._upgrades = this._filterUpgrades(data.upgrades);
super.onHandshake(data);
}
/**
* Filters upgrades, returning only those matching client transports.
*
* @param {Array} upgrades - server upgrades
* @private
*/
_filterUpgrades(upgrades) {
const filteredUpgrades = [];
for (let i = 0; i < upgrades.length; i++) {
if (~this.transports.indexOf(upgrades[i]))
filteredUpgrades.push(upgrades[i]);
}
return filteredUpgrades;
}
}
/**
* This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
* with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
*
* This class comes with an upgrade mechanism, which means that once the connection is established with the first
* low-level transport, it will try to upgrade to a better transport.
*
* @example
* import { Socket } from "engine.io-client";
*
* const socket = new Socket();
*
* socket.on("open", () => {
* socket.send("hello");
* });
*
* @see SocketWithoutUpgrade
* @see SocketWithUpgrade
*/
export class Socket extends SocketWithUpgrade {
constructor(uri, opts = {}) {
const o = typeof uri === "object" ? uri : opts;
if (!o.transports ||
(o.transports && typeof o.transports[0] === "string")) {
o.transports = (o.transports || ["polling", "websocket", "webtransport"])
.map((transportName) => DEFAULT_TRANSPORTS[transportName])
.filter((t) => !!t);
}
super(uri, o);
}
}

106
node_modules/engine.io-client/build/esm/transport.d.ts generated vendored Normal file
View File

@ -0,0 +1,106 @@
import type { Packet, RawData } from "engine.io-parser";
import { Emitter } from "@socket.io/component-emitter";
import type { Socket, SocketOptions } from "./socket.js";
export declare class TransportError extends Error {
readonly description: any;
readonly context: any;
readonly type = "TransportError";
constructor(reason: string, description: any, context: any);
}
export interface CloseDetails {
description: string;
context?: unknown;
}
interface TransportReservedEvents {
open: () => void;
error: (err: TransportError) => void;
packet: (packet: Packet) => void;
close: (details?: CloseDetails) => void;
poll: () => void;
pollComplete: () => void;
drain: () => void;
}
type TransportState = "opening" | "open" | "closed" | "pausing" | "paused";
export declare abstract class Transport extends Emitter<Record<never, never>, Record<never, never>, TransportReservedEvents> {
query: Record<string, string>;
writable: boolean;
protected opts: SocketOptions;
protected supportsBinary: boolean;
protected readyState: TransportState;
protected socket: Socket;
protected setTimeoutFn: typeof setTimeout;
/**
* Transport abstract constructor.
*
* @param {Object} opts - options
* @protected
*/
constructor(opts: any);
/**
* Emits an error.
*
* @param {String} reason
* @param description
* @param context - the error context
* @return {Transport} for chaining
* @protected
*/
protected onError(reason: string, description: any, context?: any): this;
/**
* Opens the transport.
*/
open(): this;
/**
* Closes the transport.
*/
close(): this;
/**
* Sends multiple packets.
*
* @param {Array} packets
*/
send(packets: any): void;
/**
* Called upon open
*
* @protected
*/
protected onOpen(): void;
/**
* Called with data.
*
* @param {String} data
* @protected
*/
protected onData(data: RawData): void;
/**
* Called with a decoded packet.
*
* @protected
*/
protected onPacket(packet: Packet): void;
/**
* Called upon close.
*
* @protected
*/
protected onClose(details?: CloseDetails): void;
/**
* The name of the transport
*/
abstract get name(): string;
/**
* Pauses the transport, in order not to lose packets during an upgrade.
*
* @param onPause
*/
pause(onPause: () => void): void;
protected createUri(schema: string, query?: Record<string, unknown>): string;
private _hostname;
private _port;
private _query;
protected abstract doOpen(): any;
protected abstract doClose(): any;
protected abstract write(packets: Packet[]): any;
}
export {};

142
node_modules/engine.io-client/build/esm/transport.js generated vendored Normal file
View File

@ -0,0 +1,142 @@
import { decodePacket } from "engine.io-parser";
import { Emitter } from "@socket.io/component-emitter";
import { installTimerFunctions } from "./util.js";
import { encode } from "./contrib/parseqs.js";
export class TransportError extends Error {
constructor(reason, description, context) {
super(reason);
this.description = description;
this.context = context;
this.type = "TransportError";
}
}
export class Transport extends Emitter {
/**
* Transport abstract constructor.
*
* @param {Object} opts - options
* @protected
*/
constructor(opts) {
super();
this.writable = false;
installTimerFunctions(this, opts);
this.opts = opts;
this.query = opts.query;
this.socket = opts.socket;
this.supportsBinary = !opts.forceBase64;
}
/**
* Emits an error.
*
* @param {String} reason
* @param description
* @param context - the error context
* @return {Transport} for chaining
* @protected
*/
onError(reason, description, context) {
super.emitReserved("error", new TransportError(reason, description, context));
return this;
}
/**
* Opens the transport.
*/
open() {
this.readyState = "opening";
this.doOpen();
return this;
}
/**
* Closes the transport.
*/
close() {
if (this.readyState === "opening" || this.readyState === "open") {
this.doClose();
this.onClose();
}
return this;
}
/**
* Sends multiple packets.
*
* @param {Array} packets
*/
send(packets) {
if (this.readyState === "open") {
this.write(packets);
}
else {
// this might happen if the transport was silently closed in the beforeunload event handler
}
}
/**
* Called upon open
*
* @protected
*/
onOpen() {
this.readyState = "open";
this.writable = true;
super.emitReserved("open");
}
/**
* Called with data.
*
* @param {String} data
* @protected
*/
onData(data) {
const packet = decodePacket(data, this.socket.binaryType);
this.onPacket(packet);
}
/**
* Called with a decoded packet.
*
* @protected
*/
onPacket(packet) {
super.emitReserved("packet", packet);
}
/**
* Called upon close.
*
* @protected
*/
onClose(details) {
this.readyState = "closed";
super.emitReserved("close", details);
}
/**
* Pauses the transport, in order not to lose packets during an upgrade.
*
* @param onPause
*/
pause(onPause) { }
createUri(schema, query = {}) {
return (schema +
"://" +
this._hostname() +
this._port() +
this.opts.path +
this._query(query));
}
_hostname() {
const hostname = this.opts.hostname;
return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
}
_port() {
if (this.opts.port &&
((this.opts.secure && Number(this.opts.port !== 443)) ||
(!this.opts.secure && Number(this.opts.port) !== 80))) {
return ":" + this.opts.port;
}
else {
return "";
}
}
_query(query) {
const encodedQuery = encode(query);
return encodedQuery.length ? "?" + encodedQuery : "";
}
}

View File

@ -0,0 +1,8 @@
import { XHR } from "./polling-xhr.node.js";
import { WS } from "./websocket.node.js";
import { WT } from "./webtransport.js";
export declare const transports: {
websocket: typeof WS;
webtransport: typeof WT;
polling: typeof XHR;
};

View File

@ -0,0 +1,8 @@
import { XHR } from "./polling-xhr.node.js";
import { WS } from "./websocket.node.js";
import { WT } from "./webtransport.js";
export const transports = {
websocket: WS,
webtransport: WT,
polling: XHR,
};

View File

@ -0,0 +1,15 @@
import { Polling } from "./polling.js";
/**
* HTTP long-polling based on the built-in `fetch()` method.
*
* Usage: browser, Node.js (since v18), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/fetch
* @see https://caniuse.com/fetch
* @see https://nodejs.org/api/globals.html#fetch
*/
export declare class Fetch extends Polling {
doPoll(): void;
doWrite(data: string, callback: () => void): void;
private _fetch;
}

View File

@ -0,0 +1,56 @@
import { Polling } from "./polling.js";
/**
* HTTP long-polling based on the built-in `fetch()` method.
*
* Usage: browser, Node.js (since v18), Deno, Bun
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/fetch
* @see https://caniuse.com/fetch
* @see https://nodejs.org/api/globals.html#fetch
*/
export class Fetch extends Polling {
doPoll() {
this._fetch()
.then((res) => {
if (!res.ok) {
return this.onError("fetch read error", res.status, res);
}
res.text().then((data) => this.onData(data));
})
.catch((err) => {
this.onError("fetch read error", err);
});
}
doWrite(data, callback) {
this._fetch(data)
.then((res) => {
if (!res.ok) {
return this.onError("fetch write error", res.status, res);
}
callback();
})
.catch((err) => {
this.onError("fetch write error", err);
});
}
_fetch(data) {
var _a;
const isPost = data !== undefined;
const headers = new Headers(this.opts.extraHeaders);
if (isPost) {
headers.set("content-type", "text/plain;charset=UTF-8");
}
(_a = this.socket._cookieJar) === null || _a === void 0 ? void 0 : _a.appendCookies(headers);
return fetch(this.uri(), {
method: isPost ? "POST" : "GET",
body: isPost ? data : null,
headers,
credentials: this.opts.withCredentials ? "include" : "omit",
}).then((res) => {
var _a;
// @ts-ignore getSetCookie() was added in Node.js v19.7.0
(_a = this.socket._cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(res.headers.getSetCookie());
return res;
});
}
}

View File

@ -0,0 +1,108 @@
import { Polling } from "./polling.js";
import { Emitter } from "@socket.io/component-emitter";
import type { SocketOptions } from "../socket.js";
import type { CookieJar } from "../globals.node.js";
import type { RawData } from "engine.io-parser";
export declare abstract class BaseXHR extends Polling {
protected readonly xd: boolean;
private pollXhr;
/**
* XHR Polling constructor.
*
* @param {Object} opts
* @package
*/
constructor(opts: any);
/**
* Creates a request.
*
* @private
*/
abstract request(opts?: Record<string, any>): any;
/**
* Sends data.
*
* @param {String} data to send.
* @param {Function} called upon flush.
* @private
*/
doWrite(data: any, fn: any): void;
/**
* Starts a poll cycle.
*
* @private
*/
doPoll(): void;
}
interface RequestReservedEvents {
success: () => void;
data: (data: RawData) => void;
error: (err: number | Error, context: unknown) => void;
}
export type RequestOptions = SocketOptions & {
method?: string;
data?: RawData;
xd: boolean;
cookieJar: CookieJar;
};
export declare class Request extends Emitter<Record<never, never>, Record<never, never>, RequestReservedEvents> {
private readonly createRequest;
private readonly _opts;
private readonly _method;
private readonly _uri;
private readonly _data;
private _xhr;
private setTimeoutFn;
private _index;
static requestsCount: number;
static requests: {};
/**
* Request constructor
*
* @param {Object} options
* @package
*/
constructor(createRequest: (opts: RequestOptions) => XMLHttpRequest, uri: string, opts: RequestOptions);
/**
* Creates the XHR object and sends the request.
*
* @private
*/
private _create;
/**
* Called upon error.
*
* @private
*/
private _onError;
/**
* Cleans up house.
*
* @private
*/
private _cleanup;
/**
* Called upon load.
*
* @private
*/
private _onLoad;
/**
* Aborts the request.
*
* @package
*/
abort(): void;
}
/**
* HTTP long-polling based on the built-in `XMLHttpRequest` object.
*
* Usage: browser
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
export declare class XHR extends BaseXHR {
constructor(opts: any);
request(opts?: Record<string, any>): Request;
}
export {};

View File

@ -0,0 +1,271 @@
import { Polling } from "./polling.js";
import { Emitter } from "@socket.io/component-emitter";
import { installTimerFunctions, pick } from "../util.js";
import { globalThisShim as globalThis } from "../globals.node.js";
import { hasCORS } from "../contrib/has-cors.js";
function empty() { }
export class BaseXHR extends Polling {
/**
* XHR Polling constructor.
*
* @param {Object} opts
* @package
*/
constructor(opts) {
super(opts);
if (typeof location !== "undefined") {
const isSSL = "https:" === location.protocol;
let port = location.port;
// some user agents have empty `location.port`
if (!port) {
port = isSSL ? "443" : "80";
}
this.xd =
(typeof location !== "undefined" &&
opts.hostname !== location.hostname) ||
port !== opts.port;
}
}
/**
* Sends data.
*
* @param {String} data to send.
* @param {Function} called upon flush.
* @private
*/
doWrite(data, fn) {
const req = this.request({
method: "POST",
data: data,
});
req.on("success", fn);
req.on("error", (xhrStatus, context) => {
this.onError("xhr post error", xhrStatus, context);
});
}
/**
* Starts a poll cycle.
*
* @private
*/
doPoll() {
const req = this.request();
req.on("data", this.onData.bind(this));
req.on("error", (xhrStatus, context) => {
this.onError("xhr poll error", xhrStatus, context);
});
this.pollXhr = req;
}
}
export class Request extends Emitter {
/**
* Request constructor
*
* @param {Object} options
* @package
*/
constructor(createRequest, uri, opts) {
super();
this.createRequest = createRequest;
installTimerFunctions(this, opts);
this._opts = opts;
this._method = opts.method || "GET";
this._uri = uri;
this._data = undefined !== opts.data ? opts.data : null;
this._create();
}
/**
* Creates the XHR object and sends the request.
*
* @private
*/
_create() {
var _a;
const opts = pick(this._opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
opts.xdomain = !!this._opts.xd;
const xhr = (this._xhr = this.createRequest(opts));
try {
xhr.open(this._method, this._uri, true);
try {
if (this._opts.extraHeaders) {
// @ts-ignore
xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
for (let i in this._opts.extraHeaders) {
if (this._opts.extraHeaders.hasOwnProperty(i)) {
xhr.setRequestHeader(i, this._opts.extraHeaders[i]);
}
}
}
}
catch (e) { }
if ("POST" === this._method) {
try {
xhr.setRequestHeader("Content-type", "text/plain;charset=UTF-8");
}
catch (e) { }
}
try {
xhr.setRequestHeader("Accept", "*/*");
}
catch (e) { }
(_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
// ie6 check
if ("withCredentials" in xhr) {
xhr.withCredentials = this._opts.withCredentials;
}
if (this._opts.requestTimeout) {
xhr.timeout = this._opts.requestTimeout;
}
xhr.onreadystatechange = () => {
var _a;
if (xhr.readyState === 3) {
(_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(
// @ts-ignore
xhr.getResponseHeader("set-cookie"));
}
if (4 !== xhr.readyState)
return;
if (200 === xhr.status || 1223 === xhr.status) {
this._onLoad();
}
else {
// make sure the `error` event handler that's user-set
// does not throw in the same tick and gets caught here
this.setTimeoutFn(() => {
this._onError(typeof xhr.status === "number" ? xhr.status : 0);
}, 0);
}
};
xhr.send(this._data);
}
catch (e) {
// Need to defer since .create() is called directly from the constructor
// and thus the 'error' event can only be only bound *after* this exception
// occurs. Therefore, also, we cannot throw here at all.
this.setTimeoutFn(() => {
this._onError(e);
}, 0);
return;
}
if (typeof document !== "undefined") {
this._index = Request.requestsCount++;
Request.requests[this._index] = this;
}
}
/**
* Called upon error.
*
* @private
*/
_onError(err) {
this.emitReserved("error", err, this._xhr);
this._cleanup(true);
}
/**
* Cleans up house.
*
* @private
*/
_cleanup(fromError) {
if ("undefined" === typeof this._xhr || null === this._xhr) {
return;
}
this._xhr.onreadystatechange = empty;
if (fromError) {
try {
this._xhr.abort();
}
catch (e) { }
}
if (typeof document !== "undefined") {
delete Request.requests[this._index];
}
this._xhr = null;
}
/**
* Called upon load.
*
* @private
*/
_onLoad() {
const data = this._xhr.responseText;
if (data !== null) {
this.emitReserved("data", data);
this.emitReserved("success");
this._cleanup();
}
}
/**
* Aborts the request.
*
* @package
*/
abort() {
this._cleanup();
}
}
Request.requestsCount = 0;
Request.requests = {};
/**
* Aborts pending requests when unloading the window. This is needed to prevent
* memory leaks (e.g. when using IE) and to ensure that no spurious error is
* emitted.
*/
if (typeof document !== "undefined") {
// @ts-ignore
if (typeof attachEvent === "function") {
// @ts-ignore
attachEvent("onunload", unloadHandler);
}
else if (typeof addEventListener === "function") {
const terminationEvent = "onpagehide" in globalThis ? "pagehide" : "unload";
addEventListener(terminationEvent, unloadHandler, false);
}
}
function unloadHandler() {
for (let i in Request.requests) {
if (Request.requests.hasOwnProperty(i)) {
Request.requests[i].abort();
}
}
}
const hasXHR2 = (function () {
const xhr = newRequest({
xdomain: false,
});
return xhr && xhr.responseType !== null;
})();
/**
* HTTP long-polling based on the built-in `XMLHttpRequest` object.
*
* Usage: browser
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
export class XHR extends BaseXHR {
constructor(opts) {
super(opts);
const forceBase64 = opts && opts.forceBase64;
this.supportsBinary = hasXHR2 && !forceBase64;
}
request(opts = {}) {
Object.assign(opts, { xd: this.xd }, this.opts);
return new Request(newRequest, this.uri(), opts);
}
}
function newRequest(opts) {
const xdomain = opts.xdomain;
// XMLHttpRequest can be disabled on IE
try {
if ("undefined" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
return new XMLHttpRequest();
}
}
catch (e) { }
if (!xdomain) {
try {
return new globalThis[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
}
catch (e) { }
}
}

View File

@ -0,0 +1,11 @@
import { BaseXHR, Request } from "./polling-xhr.js";
/**
* HTTP long-polling based on the `XMLHttpRequest` object provided by the `xmlhttprequest-ssl` package.
*
* Usage: Node.js, Deno (compat), Bun (compat)
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
*/
export declare class XHR extends BaseXHR {
request(opts?: Record<string, any>): Request;
}

Some files were not shown because too many files have changed in this diff Show More