rsshub
Version:
Make RSS Great Again!
4,925 lines • 160 kB
JavaScript
import { t as config } from "./config-Bpyy15zS.mjs";
import { t as logger } from "./logger-BPV-Cx6k.mjs";
import { createRequire } from "node:module";
import { createFetch } from "ofetch";
import ie from "http";
import U from "https";
import { fileURLToPath } from "url";
import { dirname, resolve } from "path";
import { Writable } from "stream";
import R from "node:zlib";
import { isUtf8 } from "node:buffer";
import ue from "net";
import path from "node:path";
import { fileURLToPath as fileURLToPath$1 } from "node:url";
import I from "fs";
import { fork } from "child_process";
import x from "undici";
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __esmMin = (fn, res, err) => () => {
if (err) throw err[0];
try {
return fn && (res = fn(fn = 0)), res;
} catch (e) {
throw err = [e], e;
}
};
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
//#endregion
//#region node_modules/.pnpm/node-network-devtools@1.0.30_undici@8.10.0_utf-8-validate@5.0.10/node_modules/node-network-devtools/dist/common-D7uiq4bu.mjs
var u = class u {
constructor(e) {
typeof e == "string" && this.parse(e), e instanceof u && Object.assign(this, e);
}
parse(e) {
if (e.match(/^\s*[-]{4,}$/)) return this.fileName = e, this;
const t = e.match(/at (?:(.+?)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/);
if (!t) return this;
let r = null, o = null, i = null, m = null, c = null, f = t[5] === "native";
if (t[1]) {
i = t[1];
let a = i.lastIndexOf(".");
if (i[a - 1] == "." && a--, a > 0) {
r = i.substr(0, a), o = i.substr(a + 1);
const l = r.indexOf(".Module");
l > 0 && (i = i.substr(l + 1), r = r.substr(0, l));
}
}
o && (m = r, c = o), o === "<anonymous>" && (c = null, i = null);
const h = {
fileName: t[2] || null,
lineNumber: parseInt(t[3], 10) || null,
functionName: i,
typeName: m,
methodName: c,
columnNumber: parseInt(t[4], 10) || null,
native: f
};
return Object.assign(this, h), this;
}
valueOf() {
return {
fileName: this.fileName,
lineNumber: this.lineNumber,
functionName: this.functionName,
typeName: this.typeName,
methodName: this.methodName,
columnNumber: this.columnNumber,
native: this.native
};
}
toString() {
return JSON.stringify(this.valueOf());
}
};
const p = [
/\((internal\/)?async_hooks\.js:/,
/\(\//,
/node_modules/
];
function N$1(s) {
const e = /* @__PURE__ */ Object.create(null);
return s ? e.stack = s : (Error.stackTraceLimit = Infinity, Error.captureStackTrace(e)), e.stack.split(`
`).slice(1).map((r) => new u(r));
}
function b$1(s) {
return s.filter((n) => !p.some((t) => t.test(n.fileName || "")));
}
console.log.bind(console, "\x1B[36m[node-network-debugger]:", "\x1B[32m");
const _ = console.warn.bind(console, "\x1B[36m[node-network-debugger](warn):", "\x1B[33m");
const w$1 = () => (/* @__PURE__ */ new Date()).getTime() / 1e3;
function E() {
let s = (/* @__PURE__ */ new Date()).getTime();
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(n) {
const t = (s + Math.random() * 16) % 16 | 0;
return s = Math.floor(s / 16), (n === "x" ? t : t & 3 | 8).toString(16);
});
}
function v$1(s) {
let e = 0, n, t;
if (s.length === 0) return e.toString(36);
for (n = 0; n < s.length; n++) t = s.charCodeAt(n), e = (e << 5) - e + t, e |= 0;
return e.toString(36);
}
var j$1 = class {
constructor(e) {
e ? (this.id = e.id, this.responseInfo = e.responseInfo, Object.assign(this, e)) : (this.id = E(), this.responseInfo = {});
}
loadCallFrames(e) {
const t = b$1(N$1(e)).map((r) => {
const o = r.fileName || "";
return {
columnNumber: r.columnNumber || 0,
functionName: r.functionName || "",
lineNumber: r.lineNumber || 0,
url: o.startsWith("/") ? `file://${o}` : o
};
});
t.length > 0 && (this.initiator = {
type: "script",
stack: { callFrames: t }
});
}
isHiden() {
return this.isWebSocket() && ["http://127.0.0.1/", "ws://127.0.0.1/"].includes(this.url);
}
isWebSocket() {
return this.requestHeaders?.Upgrade === "websocket" || this.requestHeaders?.upgrade === "websocket";
}
};
const D = Number(process.env.NETWORK_PORT || 5270);
const I$1 = Number(process.env.NETWORK_SERVER_PORT || 5271);
Number(process.env.REMOTE_DEBUGGER_PORT || 9333);
process.env.NETWORK_DEBUG_MODE;
const H$1 = dirname(fileURLToPath(import.meta.url));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/constants.js
var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const BINARY_TYPES = [
"nodebuffer",
"arraybuffer",
"fragments"
];
const hasBlob = typeof Blob !== "undefined";
if (hasBlob) BINARY_TYPES.push("blob");
module.exports = {
BINARY_TYPES,
CLOSE_TIMEOUT: 3e4,
EMPTY_BUFFER: Buffer.alloc(0),
GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
hasBlob,
kForOnEventAttribute: Symbol("kIsForOnEventAttribute"),
kListener: Symbol("kListener"),
kStatusCode: Symbol("status-code"),
kWebSocket: Symbol("websocket"),
NOOP: () => {}
};
}));
//#endregion
//#region node_modules/.pnpm/tsdown@0.22.14_@typescript+typescript6@6.0.2_oxc-resolver@11.24.2_tsx@4.23.12_unrun@0.3.1/node_modules/tsdown/esm-shims.js
var getFilename, getDirname, __dirname;
var init_esm_shims = __esmMin((() => {
getFilename = () => fileURLToPath$1(import.meta.url);
getDirname = () => path.dirname(getFilename());
__dirname = /* @__PURE__ */ getDirname();
}));
//#endregion
//#region node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/node-gyp-build.js
var require_node_gyp_build$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
var fs = __require("fs");
var path$1 = __require("path");
var os = __require("os");
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
var vars = process.config && process.config.variables || {};
var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
var abi = process.versions.modules;
var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
var arch = process.env.npm_config_arch || os.arch();
var platform = process.env.npm_config_platform || os.platform();
var libc = process.env.LIBC || (isAlpine(platform) ? "musl" : "glibc");
var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
var uv = (process.versions.uv || "").split(".")[0];
module.exports = load;
function load(dir) {
return runtimeRequire(load.resolve(dir));
}
load.resolve = load.path = function(dir) {
dir = path$1.resolve(dir || ".");
try {
var name = runtimeRequire(path$1.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
if (process.env[name + "_PREBUILD"]) dir = process.env[name + "_PREBUILD"];
} catch (err) {}
if (!prebuildsOnly) {
var release = getFirst(path$1.join(dir, "build/Release"), matchBuild);
if (release) return release;
var debug = getFirst(path$1.join(dir, "build/Debug"), matchBuild);
if (debug) return debug;
}
var prebuild = resolve(dir);
if (prebuild) return prebuild;
var nearby = resolve(path$1.dirname(process.execPath));
if (nearby) return nearby;
var target = [
"platform=" + platform,
"arch=" + arch,
"runtime=" + runtime,
"abi=" + abi,
"uv=" + uv,
armv ? "armv=" + armv : "",
"libc=" + libc,
"node=" + process.versions.node,
process.versions.electron ? "electron=" + process.versions.electron : "",
typeof __webpack_require__ === "function" ? "webpack=true" : ""
].filter(Boolean).join(" ");
throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
function resolve(dir) {
var tuple = readdirSync(path$1.join(dir, "prebuilds")).map(parseTuple).filter(matchTuple(platform, arch)).sort(compareTuples)[0];
if (!tuple) return;
var prebuilds = path$1.join(dir, "prebuilds", tuple.name);
var winner = readdirSync(prebuilds).map(parseTags).filter(matchTags(runtime, abi)).sort(compareTags(runtime))[0];
if (winner) return path$1.join(prebuilds, winner.file);
}
};
function readdirSync(dir) {
try {
return fs.readdirSync(dir);
} catch (err) {
return [];
}
}
function getFirst(dir, filter) {
var files = readdirSync(dir).filter(filter);
return files[0] && path$1.join(dir, files[0]);
}
function matchBuild(name) {
return /\.node$/.test(name);
}
function parseTuple(name) {
var arr = name.split("-");
if (arr.length !== 2) return;
var platform = arr[0];
var architectures = arr[1].split("+");
if (!platform) return;
if (!architectures.length) return;
if (!architectures.every(Boolean)) return;
return {
name,
platform,
architectures
};
}
function matchTuple(platform, arch) {
return function(tuple) {
if (tuple == null) return false;
if (tuple.platform !== platform) return false;
return tuple.architectures.includes(arch);
};
}
function compareTuples(a, b) {
return a.architectures.length - b.architectures.length;
}
function parseTags(file) {
var arr = file.split(".");
var extension = arr.pop();
var tags = {
file,
specificity: 0
};
if (extension !== "node") return;
for (var i = 0; i < arr.length; i++) {
var tag = arr[i];
if (tag === "node" || tag === "electron" || tag === "node-webkit") tags.runtime = tag;
else if (tag === "napi") tags.napi = true;
else if (tag.slice(0, 3) === "abi") tags.abi = tag.slice(3);
else if (tag.slice(0, 2) === "uv") tags.uv = tag.slice(2);
else if (tag.slice(0, 4) === "armv") tags.armv = tag.slice(4);
else if (tag === "glibc" || tag === "musl") tags.libc = tag;
else continue;
tags.specificity++;
}
return tags;
}
function matchTags(runtime, abi) {
return function(tags) {
if (tags == null) return false;
if (tags.runtime && tags.runtime !== runtime && !runtimeAgnostic(tags)) return false;
if (tags.abi && tags.abi !== abi && !tags.napi) return false;
if (tags.uv && tags.uv !== uv) return false;
if (tags.armv && tags.armv !== armv) return false;
if (tags.libc && tags.libc !== libc) return false;
return true;
};
}
function runtimeAgnostic(tags) {
return tags.runtime === "node" && tags.napi;
}
function compareTags(runtime) {
return function(a, b) {
if (a.runtime !== b.runtime) return a.runtime === runtime ? -1 : 1;
else if (a.abi !== b.abi) return a.abi ? -1 : 1;
else if (a.specificity !== b.specificity) return a.specificity > b.specificity ? -1 : 1;
else return 0;
};
}
function isNwjs() {
return !!(process.versions && process.versions.nw);
}
function isElectron() {
if (process.versions && process.versions.electron) return true;
if (process.env.ELECTRON_RUN_AS_NODE) return true;
return typeof window !== "undefined" && window.process && window.process.type === "renderer";
}
function isAlpine(platform) {
return platform === "linux" && fs.existsSync("/etc/alpine-release");
}
load.parseTags = parseTags;
load.matchTags = matchTags;
load.compareTags = compareTags;
load.parseTuple = parseTuple;
load.matchTuple = matchTuple;
load.compareTuples = compareTuples;
}));
//#endregion
//#region node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/index.js
var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
if (typeof runtimeRequire.addon === "function") module.exports = runtimeRequire.addon.bind(runtimeRequire);
else module.exports = require_node_gyp_build$1();
}));
//#endregion
//#region node_modules/.pnpm/bufferutil@4.1.0/node_modules/bufferutil/fallback.js
var require_fallback$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
/**
* Masks a buffer using the given mask.
*
* @param {Buffer} source The buffer to mask
* @param {Buffer} mask The mask to use
* @param {Buffer} output The buffer where to store the result
* @param {Number} offset The offset at which to start writing
* @param {Number} length The number of bytes to mask.
* @public
*/
const mask = (source, mask, output, offset, length) => {
for (var i = 0; i < length; i++) output[offset + i] = source[i] ^ mask[i & 3];
};
/**
* Unmasks a buffer using the given mask.
*
* @param {Buffer} buffer The buffer to unmask
* @param {Buffer} mask The mask to use
* @public
*/
const unmask = (buffer, mask) => {
const length = buffer.length;
for (var i = 0; i < length; i++) buffer[i] ^= mask[i & 3];
};
module.exports = {
mask,
unmask
};
}));
//#endregion
//#region node_modules/.pnpm/bufferutil@4.1.0/node_modules/bufferutil/index.js
var require_bufferutil = /* @__PURE__ */ __commonJSMin(((exports, module) => {
init_esm_shims();
try {
module.exports = require_node_gyp_build()(__dirname);
} catch (e) {
module.exports = require_fallback$1();
}
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/buffer-util.js
var require_buffer_util = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const { EMPTY_BUFFER } = require_constants();
const FastBuffer = Buffer[Symbol.species];
/**
* Merges an array of buffers into a new buffer.
*
* @param {Buffer[]} list The array of buffers to concat
* @param {Number} totalLength The total length of buffers in the list
* @return {Buffer} The resulting buffer
* @public
*/
function concat(list, totalLength) {
if (list.length === 0) return EMPTY_BUFFER;
if (list.length === 1) return list[0];
const target = Buffer.allocUnsafe(totalLength);
let offset = 0;
for (let i = 0; i < list.length; i++) {
const buf = list[i];
target.set(buf, offset);
offset += buf.length;
}
if (offset < totalLength) return new FastBuffer(target.buffer, target.byteOffset, offset);
return target;
}
/**
* Masks a buffer using the given mask.
*
* @param {Buffer} source The buffer to mask
* @param {Buffer} mask The mask to use
* @param {Buffer} output The buffer where to store the result
* @param {Number} offset The offset at which to start writing
* @param {Number} length The number of bytes to mask.
* @public
*/
function _mask(source, mask, output, offset, length) {
for (let i = 0; i < length; i++) output[offset + i] = source[i] ^ mask[i & 3];
}
/**
* Unmasks a buffer using the given mask.
*
* @param {Buffer} buffer The buffer to unmask
* @param {Buffer} mask The mask to use
* @public
*/
function _unmask(buffer, mask) {
for (let i = 0; i < buffer.length; i++) buffer[i] ^= mask[i & 3];
}
/**
* Converts a buffer to an `ArrayBuffer`.
*
* @param {Buffer} buf The buffer to convert
* @return {ArrayBuffer} Converted buffer
* @public
*/
function toArrayBuffer(buf) {
if (buf.length === buf.buffer.byteLength) return buf.buffer;
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
}
/**
* Converts `data` to a `Buffer`.
*
* @param {*} data The data to convert
* @return {Buffer} The buffer
* @throws {TypeError}
* @public
*/
function toBuffer(data) {
toBuffer.readOnly = true;
if (Buffer.isBuffer(data)) return data;
let buf;
if (data instanceof ArrayBuffer) buf = new FastBuffer(data);
else if (ArrayBuffer.isView(data)) buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);
else {
buf = Buffer.from(data);
toBuffer.readOnly = false;
}
return buf;
}
module.exports = {
concat,
mask: _mask,
toArrayBuffer,
toBuffer,
unmask: _unmask
};
/* istanbul ignore else */
if (!process.env.WS_NO_BUFFER_UTIL) try {
const bufferUtil = require_bufferutil();
module.exports.mask = function(source, mask, output, offset, length) {
if (length < 48) _mask(source, mask, output, offset, length);
else bufferUtil.mask(source, mask, output, offset, length);
};
module.exports.unmask = function(buffer, mask) {
if (buffer.length < 32) _unmask(buffer, mask);
else bufferUtil.unmask(buffer, mask);
};
} catch (e) {}
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/limiter.js
var require_limiter = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const kDone = Symbol("kDone");
const kRun = Symbol("kRun");
/**
* A very simple job queue with adjustable concurrency. Adapted from
* https://github.com/STRML/async-limiter
*/
var Limiter = class {
/**
* Creates a new `Limiter`.
*
* @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
* to run concurrently
*/
constructor(concurrency) {
this[kDone] = () => {
this.pending--;
this[kRun]();
};
this.concurrency = concurrency || Infinity;
this.jobs = [];
this.pending = 0;
}
/**
* Adds a job to the queue.
*
* @param {Function} job The job to run
* @public
*/
add(job) {
this.jobs.push(job);
this[kRun]();
}
/**
* Removes a job from the queue and runs it if possible.
*
* @private
*/
[kRun]() {
if (this.pending === this.concurrency) return;
if (this.jobs.length) {
const job = this.jobs.shift();
this.pending++;
job(this[kDone]);
}
}
};
module.exports = Limiter;
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/permessage-deflate.js
var require_permessage_deflate = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const zlib = __require("zlib");
const bufferUtil = require_buffer_util();
const Limiter = require_limiter();
const { kStatusCode } = require_constants();
const FastBuffer = Buffer[Symbol.species];
const TRAILER = Buffer.from([
0,
0,
255,
255
]);
const kPerMessageDeflate = Symbol("permessage-deflate");
const kTotalLength = Symbol("total-length");
const kCallback = Symbol("callback");
const kBuffers = Symbol("buffers");
const kError = Symbol("error");
let zlibLimiter;
/**
* permessage-deflate implementation.
*/
var PerMessageDeflate = class {
/**
* Creates a PerMessageDeflate instance.
*
* @param {Object} [options] Configuration options
* @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
* for, or request, a custom client window size
* @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
* acknowledge disabling of client context takeover
* @param {Number} [options.concurrencyLimit=10] The number of concurrent
* calls to zlib
* @param {Boolean} [options.isServer=false] Create the instance in either
* server or client mode
* @param {Number} [options.maxPayload=0] The maximum allowed message length
* @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
* use of a custom server window size
* @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
* disabling of server context takeover
* @param {Number} [options.threshold=1024] Size (in bytes) below which
* messages should not be compressed if context takeover is disabled
* @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
* deflate
* @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
* inflate
*/
constructor(options) {
this._options = options || {};
this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024;
this._maxPayload = this._options.maxPayload | 0;
this._isServer = !!this._options.isServer;
this._deflate = null;
this._inflate = null;
this.params = null;
if (!zlibLimiter) {
const concurrency = this._options.concurrencyLimit !== void 0 ? this._options.concurrencyLimit : 10;
zlibLimiter = new Limiter(concurrency);
}
}
/**
* @type {String}
*/
static get extensionName() {
return "permessage-deflate";
}
/**
* Create an extension negotiation offer.
*
* @return {Object} Extension parameters
* @public
*/
offer() {
const params = {};
if (this._options.serverNoContextTakeover) params.server_no_context_takeover = true;
if (this._options.clientNoContextTakeover) params.client_no_context_takeover = true;
if (this._options.serverMaxWindowBits) params.server_max_window_bits = this._options.serverMaxWindowBits;
if (this._options.clientMaxWindowBits) params.client_max_window_bits = this._options.clientMaxWindowBits;
else if (this._options.clientMaxWindowBits == null) params.client_max_window_bits = true;
return params;
}
/**
* Accept an extension negotiation offer/response.
*
* @param {Array} configurations The extension negotiation offers/reponse
* @return {Object} Accepted configuration
* @public
*/
accept(configurations) {
configurations = this.normalizeParams(configurations);
this.params = this._isServer ? this.acceptAsServer(configurations) : this.acceptAsClient(configurations);
return this.params;
}
/**
* Releases all resources used by the extension.
*
* @public
*/
cleanup() {
if (this._inflate) {
this._inflate.close();
this._inflate = null;
}
if (this._deflate) {
const callback = this._deflate[kCallback];
this._deflate.close();
this._deflate = null;
if (callback) callback(/* @__PURE__ */ new Error("The deflate stream was closed while data was being processed"));
}
}
/**
* Accept an extension negotiation offer.
*
* @param {Array} offers The extension negotiation offers
* @return {Object} Accepted configuration
* @private
*/
acceptAsServer(offers) {
const opts = this._options;
const accepted = offers.find((params) => {
if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) return false;
return true;
});
if (!accepted) throw new Error("None of the extension offers can be accepted");
if (opts.serverNoContextTakeover) accepted.server_no_context_takeover = true;
if (opts.clientNoContextTakeover) accepted.client_no_context_takeover = true;
if (typeof opts.serverMaxWindowBits === "number") accepted.server_max_window_bits = opts.serverMaxWindowBits;
if (typeof opts.clientMaxWindowBits === "number") accepted.client_max_window_bits = opts.clientMaxWindowBits;
else if (accepted.client_max_window_bits === true || opts.clientMaxWindowBits === false) delete accepted.client_max_window_bits;
return accepted;
}
/**
* Accept the extension negotiation response.
*
* @param {Array} response The extension negotiation response
* @return {Object} Accepted configuration
* @private
*/
acceptAsClient(response) {
const params = response[0];
if (this._options.clientNoContextTakeover === false && params.client_no_context_takeover) throw new Error("Unexpected parameter \"client_no_context_takeover\"");
if (!params.client_max_window_bits) {
if (typeof this._options.clientMaxWindowBits === "number") params.client_max_window_bits = this._options.clientMaxWindowBits;
} else if (this._options.clientMaxWindowBits === false || typeof this._options.clientMaxWindowBits === "number" && params.client_max_window_bits > this._options.clientMaxWindowBits) throw new Error("Unexpected or invalid parameter \"client_max_window_bits\"");
return params;
}
/**
* Normalize parameters.
*
* @param {Array} configurations The extension negotiation offers/reponse
* @return {Array} The offers/response with normalized parameters
* @private
*/
normalizeParams(configurations) {
configurations.forEach((params) => {
Object.keys(params).forEach((key) => {
let value = params[key];
if (value.length > 1) throw new Error(`Parameter "${key}" must have only a single value`);
value = value[0];
if (key === "client_max_window_bits") {
if (value !== true) {
const num = +value;
if (!Number.isInteger(num) || num < 8 || num > 15) throw new TypeError(`Invalid value for parameter "${key}": ${value}`);
value = num;
} else if (!this._isServer) throw new TypeError(`Invalid value for parameter "${key}": ${value}`);
} else if (key === "server_max_window_bits") {
const num = +value;
if (!Number.isInteger(num) || num < 8 || num > 15) throw new TypeError(`Invalid value for parameter "${key}": ${value}`);
value = num;
} else if (key === "client_no_context_takeover" || key === "server_no_context_takeover") {
if (value !== true) throw new TypeError(`Invalid value for parameter "${key}": ${value}`);
} else throw new Error(`Unknown parameter "${key}"`);
params[key] = value;
});
});
return configurations;
}
/**
* Decompress data. Concurrency limited.
*
* @param {Buffer} data Compressed data
* @param {Boolean} fin Specifies whether or not this is the last fragment
* @param {Function} callback Callback
* @public
*/
decompress(data, fin, callback) {
zlibLimiter.add((done) => {
this._decompress(data, fin, (err, result) => {
done();
callback(err, result);
});
});
}
/**
* Compress data. Concurrency limited.
*
* @param {(Buffer|String)} data Data to compress
* @param {Boolean} fin Specifies whether or not this is the last fragment
* @param {Function} callback Callback
* @public
*/
compress(data, fin, callback) {
zlibLimiter.add((done) => {
this._compress(data, fin, (err, result) => {
done();
callback(err, result);
});
});
}
/**
* Decompress data.
*
* @param {Buffer} data Compressed data
* @param {Boolean} fin Specifies whether or not this is the last fragment
* @param {Function} callback Callback
* @private
*/
_decompress(data, fin, callback) {
const endpoint = this._isServer ? "client" : "server";
if (!this._inflate) {
const key = `${endpoint}_max_window_bits`;
const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
this._inflate = zlib.createInflateRaw({
...this._options.zlibInflateOptions,
windowBits
});
this._inflate[kPerMessageDeflate] = this;
this._inflate[kTotalLength] = 0;
this._inflate[kBuffers] = [];
this._inflate.on("error", inflateOnError);
this._inflate.on("data", inflateOnData);
}
this._inflate[kCallback] = callback;
this._inflate.write(data);
if (fin) this._inflate.write(TRAILER);
this._inflate.flush(() => {
const err = this._inflate[kError];
if (err) {
this._inflate.close();
this._inflate = null;
callback(err);
return;
}
const data = bufferUtil.concat(this._inflate[kBuffers], this._inflate[kTotalLength]);
if (this._inflate._readableState.endEmitted) {
this._inflate.close();
this._inflate = null;
} else {
this._inflate[kTotalLength] = 0;
this._inflate[kBuffers] = [];
if (fin && this.params[`${endpoint}_no_context_takeover`]) this._inflate.reset();
}
callback(null, data);
});
}
/**
* Compress data.
*
* @param {(Buffer|String)} data Data to compress
* @param {Boolean} fin Specifies whether or not this is the last fragment
* @param {Function} callback Callback
* @private
*/
_compress(data, fin, callback) {
const endpoint = this._isServer ? "server" : "client";
if (!this._deflate) {
const key = `${endpoint}_max_window_bits`;
const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
this._deflate = zlib.createDeflateRaw({
...this._options.zlibDeflateOptions,
windowBits
});
this._deflate[kTotalLength] = 0;
this._deflate[kBuffers] = [];
this._deflate.on("data", deflateOnData);
}
this._deflate[kCallback] = callback;
this._deflate.write(data);
this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {
if (!this._deflate) return;
let data = bufferUtil.concat(this._deflate[kBuffers], this._deflate[kTotalLength]);
if (fin) data = new FastBuffer(data.buffer, data.byteOffset, data.length - 4);
this._deflate[kCallback] = null;
this._deflate[kTotalLength] = 0;
this._deflate[kBuffers] = [];
if (fin && this.params[`${endpoint}_no_context_takeover`]) this._deflate.reset();
callback(null, data);
});
}
};
module.exports = PerMessageDeflate;
/**
* The listener of the `zlib.DeflateRaw` stream `'data'` event.
*
* @param {Buffer} chunk A chunk of data
* @private
*/
function deflateOnData(chunk) {
this[kBuffers].push(chunk);
this[kTotalLength] += chunk.length;
}
/**
* The listener of the `zlib.InflateRaw` stream `'data'` event.
*
* @param {Buffer} chunk A chunk of data
* @private
*/
function inflateOnData(chunk) {
this[kTotalLength] += chunk.length;
if (this[kPerMessageDeflate]._maxPayload < 1 || this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload) {
this[kBuffers].push(chunk);
return;
}
this[kError] = /* @__PURE__ */ new RangeError("Max payload size exceeded");
this[kError].code = "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH";
this[kError][kStatusCode] = 1009;
this.removeListener("data", inflateOnData);
this.reset();
}
/**
* The listener of the `zlib.InflateRaw` stream `'error'` event.
*
* @param {Error} err The emitted error
* @private
*/
function inflateOnError(err) {
this[kPerMessageDeflate]._inflate = null;
if (this[kError]) {
this[kCallback](this[kError]);
return;
}
err[kStatusCode] = 1007;
this[kCallback](err);
}
}));
//#endregion
//#region node_modules/.pnpm/utf-8-validate@5.0.10/node_modules/utf-8-validate/fallback.js
var require_fallback = /* @__PURE__ */ __commonJSMin(((exports, module) => {
/**
* Checks if a given buffer contains only correct UTF-8.
* Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by
* Markus Kuhn.
*
* @param {Buffer} buf The buffer to check
* @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`
* @public
*/
function isValidUTF8(buf) {
const len = buf.length;
let i = 0;
while (i < len) if ((buf[i] & 128) === 0) i++;
else if ((buf[i] & 224) === 192) {
if (i + 1 === len || (buf[i + 1] & 192) !== 128 || (buf[i] & 254) === 192) return false;
i += 2;
} else if ((buf[i] & 240) === 224) {
if (i + 2 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || buf[i] === 224 && (buf[i + 1] & 224) === 128 || buf[i] === 237 && (buf[i + 1] & 224) === 160) return false;
i += 3;
} else if ((buf[i] & 248) === 240) {
if (i + 3 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || (buf[i + 3] & 192) !== 128 || buf[i] === 240 && (buf[i + 1] & 240) === 128 || buf[i] === 244 && buf[i + 1] > 143 || buf[i] > 244) return false;
i += 4;
} else return false;
return true;
}
module.exports = isValidUTF8;
}));
//#endregion
//#region node_modules/.pnpm/utf-8-validate@5.0.10/node_modules/utf-8-validate/index.js
var require_utf_8_validate = /* @__PURE__ */ __commonJSMin(((exports, module) => {
init_esm_shims();
try {
module.exports = require_node_gyp_build()(__dirname);
} catch (e) {
module.exports = require_fallback();
}
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/validation.js
var require_validation = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const { isUtf8: isUtf8$1 } = __require("buffer");
const { hasBlob } = require_constants();
const tokenChars = [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
1,
1,
1,
1,
1,
0,
0,
1,
1,
0,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
1,
0,
1,
0
];
/**
* Checks if a status code is allowed in a close frame.
*
* @param {Number} code The status code
* @return {Boolean} `true` if the status code is valid, else `false`
* @public
*/
function isValidStatusCode(code) {
return code >= 1e3 && code <= 1014 && code !== 1004 && code !== 1005 && code !== 1006 || code >= 3e3 && code <= 4999;
}
/**
* Checks if a given buffer contains only correct UTF-8.
* Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by
* Markus Kuhn.
*
* @param {Buffer} buf The buffer to check
* @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`
* @public
*/
function _isValidUTF8(buf) {
const len = buf.length;
let i = 0;
while (i < len) if ((buf[i] & 128) === 0) i++;
else if ((buf[i] & 224) === 192) {
if (i + 1 === len || (buf[i + 1] & 192) !== 128 || (buf[i] & 254) === 192) return false;
i += 2;
} else if ((buf[i] & 240) === 224) {
if (i + 2 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || buf[i] === 224 && (buf[i + 1] & 224) === 128 || buf[i] === 237 && (buf[i + 1] & 224) === 160) return false;
i += 3;
} else if ((buf[i] & 248) === 240) {
if (i + 3 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || (buf[i + 3] & 192) !== 128 || buf[i] === 240 && (buf[i + 1] & 240) === 128 || buf[i] === 244 && buf[i + 1] > 143 || buf[i] > 244) return false;
i += 4;
} else return false;
return true;
}
/**
* Determines whether a value is a `Blob`.
*
* @param {*} value The value to be tested
* @return {Boolean} `true` if `value` is a `Blob`, else `false`
* @private
*/
function isBlob(value) {
return hasBlob && typeof value === "object" && typeof value.arrayBuffer === "function" && typeof value.type === "string" && typeof value.stream === "function" && (value[Symbol.toStringTag] === "Blob" || value[Symbol.toStringTag] === "File");
}
module.exports = {
isBlob,
isValidStatusCode,
isValidUTF8: _isValidUTF8,
tokenChars
};
if (isUtf8$1) module.exports.isValidUTF8 = function(buf) {
return buf.length < 24 ? _isValidUTF8(buf) : isUtf8$1(buf);
};
else if (!process.env.WS_NO_UTF_8_VALIDATE) try {
const isValidUTF8 = require_utf_8_validate();
module.exports.isValidUTF8 = function(buf) {
return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
};
} catch (e) {}
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/receiver.js
var require_receiver = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const { Writable: Writable$1 } = __require("stream");
const PerMessageDeflate = require_permessage_deflate();
const { BINARY_TYPES, EMPTY_BUFFER, kStatusCode, kWebSocket } = require_constants();
const { concat, toArrayBuffer, unmask } = require_buffer_util();
const { isValidStatusCode, isValidUTF8 } = require_validation();
const FastBuffer = Buffer[Symbol.species];
const GET_INFO = 0;
const GET_PAYLOAD_LENGTH_16 = 1;
const GET_PAYLOAD_LENGTH_64 = 2;
const GET_MASK = 3;
const GET_DATA = 4;
const INFLATING = 5;
const DEFER_EVENT = 6;
/**
* HyBi Receiver implementation.
*
* @extends Writable
*/
var Receiver = class extends Writable$1 {
/**
* Creates a Receiver instance.
*
* @param {Object} [options] Options object
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
* any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
* multiple times in the same tick
* @param {String} [options.binaryType=nodebuffer] The type for binary data
* @param {Object} [options.extensions] An object containing the negotiated
* extensions
* @param {Boolean} [options.isServer=false] Specifies whether to operate in
* client or server mode
* @param {Number} [options.maxBufferedChunks=0] The maximum number of
* buffered data chunks
* @param {Number} [options.maxFragments=0] The maximum number of message
* fragments
* @param {Number} [options.maxPayload=0] The maximum allowed message length
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
* not to skip UTF-8 validation for text and close messages
*/
constructor(options = {}) {
super();
this._allowSynchronousEvents = options.allowSynchronousEvents !== void 0 ? options.allowSynchronousEvents : true;
this._binaryType = options.binaryType || BINARY_TYPES[0];
this._extensions = options.extensions || {};
this._isServer = !!options.isServer;
this._maxBufferedChunks = options.maxBufferedChunks | 0;
this._maxFragments = options.maxFragments | 0;
this._maxPayload = options.maxPayload | 0;
this._skipUTF8Validation = !!options.skipUTF8Validation;
this[kWebSocket] = void 0;
this._bufferedBytes = 0;
this._buffers = [];
this._compressed = false;
this._payloadLength = 0;
this._mask = void 0;
this._fragmented = 0;
this._masked = false;
this._fin = false;
this._opcode = 0;
this._totalPayloadLength = 0;
this._messageLength = 0;
this._numFragments = 0;
this._fragments = [];
this._errored = false;
this._loop = false;
this._state = GET_INFO;
}
/**
* Implements `Writable.prototype._write()`.
*
* @param {Buffer} chunk The chunk of data to write
* @param {String} encoding The character encoding of `chunk`
* @param {Function} cb Callback
* @private
*/
_write(chunk, encoding, cb) {
if (this._opcode === 8 && this._state == GET_INFO) return cb();
if (this._maxBufferedChunks > 0 && this._buffers.length >= this._maxBufferedChunks) {
cb(this.createError(RangeError, "Too many buffered chunks", false, 1008, "WS_ERR_TOO_MANY_BUFFERED_PARTS"));
return;
}
this._bufferedBytes += chunk.length;
this._buffers.push(chunk);
this.startLoop(cb);
}
/**
* Consumes `n` bytes from the buffered data.
*
* @param {Number} n The number of bytes to consume
* @return {Buffer} The consumed bytes
* @private
*/
consume(n) {
this._bufferedBytes -= n;
if (n === this._buffers[0].length) return this._buffers.shift();
if (n < this._buffers[0].length) {
const buf = this._buffers[0];
this._buffers[0] = new FastBuffer(buf.buffer, buf.byteOffset + n, buf.length - n);
return new FastBuffer(buf.buffer, buf.byteOffset, n);
}
const dst = Buffer.allocUnsafe(n);
do {
const buf = this._buffers[0];
const offset = dst.length - n;
if (n >= buf.length) dst.set(this._buffers.shift(), offset);
else {
dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
this._buffers[0] = new FastBuffer(buf.buffer, buf.byteOffset + n, buf.length - n);
}
n -= buf.length;
} while (n > 0);
return dst;
}
/**
* Starts the parsing loop.
*
* @param {Function} cb Callback
* @private
*/
startLoop(cb) {
this._loop = true;
do
switch (this._state) {
case GET_INFO:
this.getInfo(cb);
break;
case GET_PAYLOAD_LENGTH_16:
this.getPayloadLength16(cb);
break;
case GET_PAYLOAD_LENGTH_64:
this.getPayloadLength64(cb);
break;
case GET_MASK:
this.getMask();
break;
case GET_DATA:
this.getData(cb);
break;
case INFLATING:
case DEFER_EVENT:
this._loop = false;
return;
}
while (this._loop);
if (!this._errored) cb();
}
/**
* Reads the first two bytes of a frame.
*
* @param {Function} cb Callback
* @private
*/
getInfo(cb) {
if (this._bufferedBytes < 2) {
this._loop = false;
return;
}
const buf = this.consume(2);
if ((buf[0] & 48) !== 0) {
cb(this.createError(RangeError, "RSV2 and RSV3 must be clear", true, 1002, "WS_ERR_UNEXPECTED_RSV_2_3"));
return;
}
const compressed = (buf[0] & 64) === 64;
if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {
cb(this.createError(RangeError, "RSV1 must be clear", true, 1002, "WS_ERR_UNEXPECTED_RSV_1"));
return;
}
this._fin = (buf[0] & 128) === 128;
this._opcode = buf[0] & 15;
this._payloadLength = buf[1] & 127;
if (this._opcode === 0) {
if (compressed) {
cb(this.createError(RangeError, "RSV1 must be clear", true, 1002, "WS_ERR_UNEXPECTED_RSV_1"));
return;
}
if (!this._fragmented) {
cb(this.createError(RangeError, "invalid opcode 0", true, 1002, "WS_ERR_INVALID_OPCODE"));
return;
}
this._opcode = this._fragmented;
} else if (this._opcode === 1 || this._opcode === 2) {
if (this._fragmented) {
cb(this.createError(RangeError, `invalid opcode ${this._opcode}`, true, 1002, "WS_ERR_INVALID_OPCODE"));
return;
}
this._compressed = compressed;
} else if (this._opcode > 7 && this._opcode < 11) {
if (!this._fin) {
cb(this.createError(RangeError, "FIN must be set", true, 1002, "WS_ERR_EXPECTED_FIN"));
return;
}
if (compressed) {
cb(this.createError(RangeError, "RSV1 must be clear", true, 1002, "WS_ERR_UNEXPECTED_RSV_1"));
return;
}
if (this._payloadLength > 125 || this._opcode === 8 && this._payloadLength === 1) {
cb(this.createError(RangeError, `invalid payload length ${this._payloadLength}`, true, 1002, "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH"));
return;
}
} else {
cb(this.createError(RangeError, `invalid opcode ${this._opcode}`, true, 1002, "WS_ERR_INVALID_OPCODE"));
return;
}
if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
this._masked = (buf[1] & 128) === 128;
if (this._isServer) {
if (!this._masked) {
cb(this.createError(RangeError, "MASK must be set", true, 1002, "WS_ERR_EXPECTED_MASK"));
return;
}
} else if (this._masked) {
cb(this.createError(RangeError, "MASK must be clear", true, 1002, "WS_ERR_UNEXPECTED_MASK"));
return;
}
if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
else this.haveLength(cb);
}
/**
* Gets extended payload length (7+16).
*
* @param {Function} cb Callback
* @private
*/
getPayloadLength16(cb) {
if (this._bufferedBytes < 2) {
this._loop = false;
return;
}
this._payloadLength = this.consume(2).readUInt16BE(0);
this.haveLength(cb);
}
/**
* Gets extended payload length (7+64).
*
* @param {Function} cb Callback
* @private
*/
getPayloadLength64(cb) {
if (this._bufferedBytes < 8) {
this._loop = false;
return;
}
const buf = this.consume(8);
const num = buf.readUInt32BE(0);
if (num > Math.pow(2, 21) - 1) {
cb(this.createError(RangeError, "Unsupported WebSocket frame: payload length > 2^53 - 1", false, 1009, "WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH"));
return;
}
this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
this.haveLength(cb);
}
/**
* Payload length has been read.
*
* @param {Function} cb Callback
* @private
*/
haveLength(cb) {
if (this._payloadLength && this._opcode < 8) {
this._totalPayloadLength += this._payloadLength;
if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
cb(this.createError(RangeError, "Max payload size exceeded", false, 1009, "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"));
return;
}
}
if (this._masked) this._state = GET_MASK;
else this._state = GET_DATA;
}
/**
* Reads mask bytes.
*
* @private
*/
getMask() {
if (this._bufferedBytes < 4) {
this._loop = false;
return;
}
this._mask = this.consume(4);
this._state = GET_DATA;
}
/**
* Reads data bytes.
*
* @param {Function} cb Callback
* @private
*/
getData(cb) {
let data = EMPTY_BUFFER;
if (this._payloadLength) {
if (this._bufferedBytes < this._payloadLength) {
this._loop = false;
return;
}
data = this.consume(this._payloadLength);
if (this._masked && (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0) unmask(data, this._mask);
}
if (this._opcode > 7) {
this.controlMessage(data, cb);
return;
}
if (this._maxFragments > 0 && ++this._numFragments > this._maxFragments) {
cb(this.createError(RangeError, "Too many message fragments", false, 1008, "WS_ERR_TOO_MANY_BUFFERED_PARTS"));
return;
}
if (this._compressed) {
this._state = INFLATING;
this.decompress(data, cb);
return;
}
if (data.length) {
this._messageLength = this._totalPayloadLength;
this._fragments.push(data);
}
this.dataMessage(cb);
}
/**
* Decompresses data.
*
* @param {Buffer} data Compressed data
* @param {Function} cb Callback
* @private
*/
decompress(data, cb) {
this._extensions[PerMessageDeflate.extensionName].decompress(data, this._fin, (err, buf) => {
if (err) return cb(err);
if (buf.length) {
this._messageLength += buf.length;
if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
cb(this.createError(RangeError, "Max payload size exceeded", false, 1009, "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"));
return;
}
this._fragments.push(buf);
}
this.dataMessage(cb);
if (this._state === GET_INFO) this.startLoop(cb);
});
}
/**
* Handles a data message.
*
* @param {Function} cb Callback
* @private
*/
dataMessage(cb) {
if (!this._fin) {
this._state = GET_INFO;
return;
}
const messageLength = this._messageLength;
const fragments = this._fragments;
this._totalPayloadLength = 0;
this._messageLength = 0;
this._fragmented = 0;
this._numFragments = 0;
this._fragments = [];
if (this._opcode === 2) {
let data;
if (this._binaryType === "nodebuffer") data = concat(fragments, messageLength);
else if (this._binaryType === "arraybuffer") data = toArrayBuffer(concat(fragments, messageLength));
else if (this._binaryType === "blob") data = new Blob(fragments);
else data = fragments;
if (this._allowSynchronousEvents) {
this.emit("message", data, true);
this._state = GET_INFO;
} else {
this._state = DEFER_EVENT;
setImmediate(() => {
this.emit("message", data, true);
this._state = GET_INFO;
this.startLoop(cb);
});
}
} else {
const buf = concat(fragments, messageLength);
if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
cb(this.createError(Error, "invalid UTF-8 sequence", true, 1007, "WS_ERR_INVALID_UTF8"));
return;
}
if (this._state === INFLATING || this._allowSynchronousEvents) {
this.emit("message", buf, false);
this._state = GET_INFO;
} else {
this._state = DEFER_EVENT;
setImmediate(() => {
this.emit("message", buf, false);
this._state = GET_INFO;
this.startLoop(cb);
});
}
}
}
/**
* Handles a control message.
*
* @param {Buffer} data Data to handle
* @return {(Error|RangeError|undefined)} A possible error
* @private
*/
controlMessage(data, cb) {
if (this._opcode === 8) {
if (data.length === 0) {
this._loop = false;
this.emit("conclude", 1005, EMPTY_BUFFER);
this.end();
} else {
const code = data.readUInt16BE(0);
if (!isValidStatusCode(code)) {
cb(this.createError(RangeError, `invalid status code ${code}`, true, 1002, "WS_ERR_INVALID_CLOSE_CODE"));
return;
}
const buf = new FastBuffer(data.buffer, data.byteOffset + 2, data.length - 2);
if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
cb(this.createError(Error, "invalid UTF-8 sequence", true, 1007, "WS_ERR_INVALID_UTF8"));
return;
}
this._loop = false;
this.emit("conclude", code, buf);
this.end();
}
this._state = GET_INFO;
return;
}
if (this._allowSynchronousEvents) {
this.emit(this._opcode === 9 ? "ping" : "pong", data);
this._state = GET_INFO;
} else {
this._state = DEFER_EVENT;
setImmediate(() => {
this.emit(this._opcode === 9 ? "ping" : "pong", data);
this._state = GET_INFO;
this.startLoop(cb);
});
}
}
/**
* Builds an error object.
*
* @param {function(new:Error|RangeError)} ErrorCtor The error constructor
* @param {String} message The error message
* @param {Boolean} prefix Specifies whether or not to add a default prefix to
* `message`
* @param {Number} statusCode The status code
* @param {String} errorCode The exposed error code
* @return {(Error|RangeError)} The error
* @private
*/
createError(ErrorCtor, message, prefix, statusCode, errorCode) {
this._loop = false;
this._errored = true;
const err = new ErrorCtor(prefix ? `Invalid WebSocket frame: ${message}` : message);
Error.captureStackTrace(err, this.createError);
err.code = errorCode;
err[kStatusCode] = statusCode;
return err;
}
};
module.exports = Receiver;
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/sender.js
var require_sender = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const { Duplex: Duplex$3 } = __require("stream");
const { randomFillSync } = __require("crypto");
const { types: { isUint8Array } } = __require("util");
const PerMessageDeflate = require_permessage_deflate();
const { EMPTY_BUFFER, kWebSocket, NOOP } = require_constants();
const { isBlob, isValidStatusCode } = require_validation();
const { mask: applyMask, toBuffer } = require_buffer_util();
const kByteLength = Symbol("kByteLength");
const maskBuffer = Buffer.alloc(4);
const RANDOM_POOL_SIZE = 8 * 1024;
let randomPool;
let randomPoolPointer = RANDOM_POOL_SIZE;
const DEFAULT = 0;
const DEFLATING = 1;
const GET_BLOB_DATA = 2;
module.exports = class Sender {
/**
* Creates a Sender instance.
*
* @param {Duplex} socket The connection socket
* @param {Object} [extensions] An object containing the negotiated extensions
* @param {Function} [generateMask] The function used to generate the masking
* key
*/
constructor(socket, extensions, generateMask) {
this._extensions = extensions || {};
if (generateMask) {
this._generateMask = generateMask;
this._maskBuffer = Buffer.alloc(4);
}
this._socket = socket;
this._firstFragment = true;
this._compress = false;
this._bufferedBytes = 0;
this._queue = [];
this._state = DEFAULT;
this.onerror = NOOP;
this[kWebSocket] = void 0;
}
/**
* Frames a piece of data according to the HyBi WebSocket protocol.
*
* @param {(Buffer|String)} data The data to frame
* @param {Object} options Options object
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
* FIN bit
* @param {Function} [options.generateMask] The function used to generate the
* masking key
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
* `data`
* @param {Buffer} [options.maskBuffer] The buffer used to store the masking
* key
* @param {Number} options.opcode The opcode
* @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
* modified
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
* RSV1 bit
* @return {(Buffer|String)[]} The framed data
* @public
*/
static frame(data, options) {
let mask;
let merge = false;
let offset = 2;
let skipMasking = false;
if (options.mask) {
mask = options.maskBuffer || maskBuffer;
if (options.generateMask) options.generateMask(mask);
else {
if (randomPoolPointer === RANDOM_POOL_SIZE) {
/* istanbul ignore else */
if (randomPool === void 0) randomPool = Buffer.alloc(RANDOM_POOL_SIZE);
randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);
randomPoolPointer = 0;
}
mask[0] = randomPool[randomPoolPointer++];
mask[1] = randomPool[randomPoolPointer++];
mask[2] = randomPool[randomPoolPointer++];
mask[3] = randomPool[randomPoolPointer++];
}
skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;
offset = 6;
}
let dataLength;
if (typeof data === "string") if ((!options.mask || skipMasking) && options[kByteLength] !== void 0) dataLength = options[kByteLength];
else {
data = Buffer.from(data);
dataLength = data.length;
}
else {
dataLength = data.length;
merge = options.mask && options.readOnly && !skipMasking;
}
let payloadLength = dataLength;
if (dataLength >= 65536) {
offset += 8;
payloadLength = 127;
} else if (dataLength > 125) {
offset += 2;
payloadLength = 126;
}
const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);
target[0] = options.fin ? options.opcode | 128 : options.opcode;
if (options.rsv1) target[0] |= 64;
target[1] = payloadLength;
if (payloadLength === 126) target.writeUInt16BE(dataLength, 2);
else if (payloadLength === 127) {
target[2] = target[3] = 0;
target.writeUIntBE(dataLength, 4, 6);
}
if (!options.mask) return [target, data];
target[1] |= 128;
target[offset - 4] = mask[0];
target[offset - 3] = mask[1];
target[offset - 2] = mask[2];
target[offset - 1] = mask[3];
if (skipMasking) return [target, data];
if (merge) {
applyMask(data, mask, target, offset, dataLength);
return [target];
}
applyMask(data, mask, data, 0, dataLength);
return [target, data];
}
/**
* Sends a close message to the other peer.
*
* @param {Number} [code] The status code component of the body
* @param {(String|Buffer)} [data] The message component of the body
* @param {Boolean} [mask=false] Specifies whether or not to mask the message
* @param {Function} [cb] Callback
* @public
*/
close(code, data, mask, cb) {
let buf;
if (code === void 0) buf = EMPTY_BUFFER;
else if (typeof code !== "number" || !isValidStatusCode(code)) throw new TypeError("First argument must be a valid error code number");
else if (data === void 0 || !data.length) {
buf = Buffer.allocUnsafe(2);
buf.writeUInt16BE(code, 0);
} else {
const length = Buffer.byteLength(data);
if (length > 123) throw new RangeError("The message must not be greater than 123 bytes");
buf = Buffer.allocUnsafe(2 + length);
buf.writeUInt16BE(code, 0);
if (typeof data === "string") buf.write(data, 2);
else if (isUint8Array(data)) buf.set(data, 2);
else throw new TypeError("Second argument must be a string or a Uint8Array");
}
const options = {
[kByteLength]: buf.length,
fin: true,
generateMask: this._generateMask,
mask,
maskBuffer: this._maskBuffer,
opcode: 8,
readOnly: false,
rsv1: false
};
if (this._state !== DEFAULT) this.enqueue([
this.dispatch,
buf,
false,
options,
cb
]);
else this.sendFrame(Sender.frame(buf, options), cb);
}
/**
* Sends a ping message to the other peer.
*
* @param {*} data The message to send
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
* @param {Function} [cb] Callback
* @public
*/
ping(data, mask, cb) {
let byteLength;
let readOnly;
if (typeof data === "string") {
byteLength = Buffer.byteLength(data);
readOnly = false;
} else if (isBlob(data)) {
byteLength = data.size;
readOnly = false;
} else {
data = toBuffer(data);
byteLength = data.length;
readOnly = toBuffer.readOnly;
}
if (byteLength > 125) throw new RangeError("The data size must not be greater than 125 bytes");
const options = {
[kByteLength]: byteLength,
fin: true,
generateMask: this._generateMask,
mask,
maskBuffer: this._maskBuffer,
opcode: 9,
readOnly,
rsv1: false
};
if (isBlob(data)) if (this._state !== DEFAULT) this.enqueue([
this.getBlobData,
data,
false,
options,
cb
]);
else this.getBlobData(data, false, options, cb);
else if (this._state !== DEFAULT) this.enqueue([
this.dispatch,
data,
false,
options,
cb
]);
else this.sendFrame(Sender.frame(data, options), cb);
}
/**
* Sends a pong message to the other peer.
*
* @param {*} data The message to send
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
* @param {Function} [cb] Callback
* @public
*/
pong(data, mask, cb) {
let byteLength;
let readOnly;
if (typeof data === "string") {
byteLength = Buffer.byteLength(data);
readOnly = false;
} else if (isBlob(data)) {
byteLength = data.size;
readOnly = false;
} else {
data = toBuffer(data);
byteLength = data.length;
readOnly = toBuffer.readOnly;
}
if (byteLength > 125) throw new RangeError("The data size must not be greater than 125 bytes");
const options = {
[kByteLength]: byteLength,
fin: true,
generateMask: this._generateMask,
mask,
maskBuffer: this._maskBuffer,
opcode: 10,
readOnly,
rsv1: false
};
if (isBlob(data)) if (this._state !== DEFAULT) this.enqueue([
this.getBlobData,
data,
false,
options,
cb
]);
else this.getBlobData(data, false, options, cb);
else if (this._state !== DEFAULT) this.enqueue([
this.dispatch,
data,
false,
options,
cb
]);
else this.sendFrame(Sender.frame(data, options), cb);
}
/**
* Sends a data message to the other peer.
*
* @param {*} data The message to send
* @param {Object} options Options object
* @param {Boolean} [options.binary=false] Specifies whether `data` is binary
* or text
* @param {Boolean} [options.compress=false] Specifies whether or not to
* compress `data`
* @param {Boolean} [options.fin=false] Specifies whether the fragment is the
* last one
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
* `data`
* @param {Function} [cb] Callback
* @public
*/
send(data, options, cb) {
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
let opcode = options.binary ? 2 : 1;
let rsv1 = options.compress;
let byteLength;
let readOnly;
if (typeof data === "string") {
byteLength = Buffer.byteLength(data);
readOnly = false;
} else if (isBlob(data)) {
byteLength = data.size;
readOnly = false;
} else {
data = toBuffer(data);
byteLength = data.length;
readOnly = toBuffer.readOnly;
}
if (this._firstFragment) {
this._firstFragment = false;
if (rsv1 && perMessageDeflate && perMessageDeflate.params[perMessageDeflate._isServer ? "server_no_context_takeover" : "client_no_context_takeover"]) rsv1 = byteLength >= perMessageDeflate._threshold;
this._compress = rsv1;
} else {
rsv1 = false;
opcode = 0;
}
if (options.fin) this._firstFragment = true;
const opts = {
[kByteLength]: byteLength,
fin: options.fin,
generateMask: this._generateMask,
mask: options.mask,
maskBuffer: this._maskBuffer,
opcode,
readOnly,
rsv1
};
if (isBlob(data)) if (this._state !== DEFAULT) this.enqueue([
this.getBlobData,
data,
this._compress,
opts,
cb
]);
else this.getBlobData(data, this._compress, opts, cb);
else if (this._state !== DEFAULT) this.enqueue([
this.dispatch,
data,
this._compress,
opts,
cb
]);
else this.dispatch(data, this._compress, opts, cb);
}
/**
* Gets the contents of a blob as binary data.
*
* @param {Blob} blob The blob
* @param {Boolean} [compress=false] Specifies whether or not to compress
* the data
* @param {Object} options Options object
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
* FIN bit
* @param {Function} [options.generateMask] The function used to generate the
* masking key
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
* `data`
* @param {Buffer} [options.maskBuffer] The buffer used to store the masking
* key
* @param {Number} options.opcode The opcode
* @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
* modified
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
* RSV1 bit
* @param {Function} [cb] Callback
* @private
*/
getBlobData(blob, compress, options, cb) {
this._bufferedBytes += options[kByteLength];
this._state = GET_BLOB_DATA;
blob.arrayBuffer().then((arrayBuffer) => {
if (this._socket.destroyed) {
const err = /* @__PURE__ */ new Error("The socket was closed while the blob was being read");
process.nextTick(callCallbacks, this, err, cb);
return;
}
this._bufferedBytes -= options[kByteLength];
const data = toBuffer(arrayBuffer);
if (!compress) {
this._state = DEFAULT;
this.sendFrame(Sender.frame(data, options), cb);
this.dequeue();
} else this.dispatch(data, compress, options, cb);
}).catch((err) => {
process.nextTick(onError, this, err, cb);
});
}
/**
* Dispatches a message.
*
* @param {(Buffer|String)} data The message to send
* @param {Boolean} [compress=false] Specifies whether or not to compress
* `data`
* @param {Object} options Options object
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
* FIN bit
* @param {Function} [options.generateMask] The function used to generate the
* masking key
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
* `data`
* @param {Buffer} [options.maskBuffer] The buffer used to store the masking
* key
* @param {Number} options.opcode The opcode
* @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
* modified
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
* RSV1 bit
* @param {Function} [cb] Callback
* @private
*/
dispatch(data, compress, options, cb) {
if (!compress) {
this.sendFrame(Sender.frame(data, options), cb);
return;
}
const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
this._bufferedBytes += options[kByteLength];
this._state = DEFLATING;
perMessageDeflate.compress(data, options.fin, (_, buf) => {
if (this._socket.destroyed) {
const err = /* @__PURE__ */ new Error("The socket was closed while data was being compressed");
callCallbacks(this, err, cb);
return;
}
this._bufferedBytes -= options[kByteLength];
this._state = DEFAULT;
options.readOnly = false;
this.sendFrame(Sender.frame(buf, options), cb);
this.dequeue();
});
}
/**
* Executes queued send operations.
*
* @private
*/
dequeue() {
while (this._state === DEFAULT && this._queue.length) {
const params = this._queue.shift();
this._bufferedBytes -= params[3][kByteLength];
Reflect.apply(params[0], this, params.slice(1));
}
}
/**
* Enqueues a send operation.
*
* @param {Array} params Send operation parameters.
* @private
*/
enqueue(params) {
this._bufferedBytes += params[3][kByteLength];
this._queue.push(params);
}
/**
* Sends a frame.
*
* @param {(Buffer | String)[]} list The frame to send
* @param {Function} [cb] Callback
* @private
*/
sendFrame(list, cb) {
if (list.length === 2) {
this._socket.cork();
this._socket.write(list[0]);
this._socket.write(list[1], cb);
this._socket.uncork();
} else this._socket.write(list[0], cb);
}
};
/**
* Calls queued callbacks with an error.
*
* @param {Sender} sender The `Sender` instance
* @param {Error} err The error to call the callbacks with
* @param {Function} [cb] The first callback
* @private
*/
function callCallbacks(sender, err, cb) {
if (typeof cb === "function") cb(err);
for (let i = 0; i < sender._queue.length; i++) {
const params = sender._queue[i];
const callback = params[params.length - 1];
if (typeof callback === "function") callback(err);
}
}
/**
* Handles a `Sender` error.
*
* @param {Sender} sender The `Sender` instance
* @param {Error} err The error
* @param {Function} [cb] The first pending callback
* @private
*/
function onError(sender, err, cb) {
callCallbacks(sender, err, cb);
sender.onerror(err);
}
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/event-target.js
var require_event_target = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const { kForOnEventAttribute, kListener } = require_constants();
const kCode = Symbol("kCode");
const kData = Symbol("kData");
const kError = Symbol("kError");
const kMessage = Symbol("kMessage");
const kReason = Symbol("kReason");
const kTarget = Symbol("kTarget");
const kType = Symbol("kType");
const kWasClean = Symbol("kWasClean");
/**
* Class representing an event.
*/
var Event = class {
/**
* Create a new `Event`.
*
* @param {String} type The name of the event
* @throws {TypeError} If the `type` argument is not specified
*/
constructor(type) {
this[kTarget] = null;
this[kType] = type;
}
/**
* @type {*}
*/
get target() {
return this[kTarget];
}
/**
* @type {String}
*/
get type() {
return this[kType];
}
};
Object.defineProperty(Event.prototype, "target", { enumerable: true });
Object.defineProperty(Event.prototype, "type", { enumerable: true });
/**
* Class representing a close event.
*
* @extends Event
*/
var CloseEvent = class extends Event {
/**
* Create a new `CloseEvent`.
*
* @param {String} type The name of the event
* @param {Object} [options] A dictionary object that allows for setting
* attributes via object members of the same name
* @param {Number} [options.code=0] The status code explaining why the
* connection was closed
* @param {String} [options.reason=''] A human-readable string explaining why
* the connection was closed
* @param {Boolean} [options.wasClean=false] Indicates whether or not the
* connection was cleanly closed
*/
constructor(type, options = {}) {
super(type);
this[kCode] = options.code === void 0 ? 0 : options.code;
this[kReason] = options.reason === void 0 ? "" : options.reason;
this[kWasClean] = options.wasClean === void 0 ? false : options.wasClean;
}
/**
* @type {Number}
*/
get code() {
return this[kCode];
}
/**
* @type {String}
*/
get reason() {
return this[kReason];
}
/**
* @type {Boolean}
*/
get wasClean() {
return this[kWasClean];
}
};
Object.defineProperty(CloseEvent.prototype, "code", { enumerable: true });
Object.defineProperty(CloseEvent.prototype, "reason", { enumerable: true });
Object.defineProperty(CloseEvent.prototype, "wasClean", { enumerable: true });
/**
* Class representing an error event.
*
* @extends Event
*/
var ErrorEvent = class extends Event {
/**
* Create a new `ErrorEvent`.
*
* @param {String} type The name of the event
* @param {Object} [options] A dictionary object that allows for setting
* attributes via object members of the same name
* @param {*} [options.error=null] The error that generated this event
* @param {String} [options.message=''] The error message
*/
constructor(type, options = {}) {
super(type);
this[kError] = options.error === void 0 ? null : options.error;
this[kMessage] = options.message === void 0 ? "" : options.message;
}
/**
* @type {*}
*/
get error() {
return this[kError];
}
/**
* @type {String}
*/
get message() {
return this[kMessage];
}
};
Object.defineProperty(ErrorEvent.prototype, "error", { enumerable: true });
Object.defineProperty(ErrorEvent.prototype, "message", { enumerable: true });
/**
* Class representing a message event.
*
* @extends Event
*/
var MessageEvent = class extends Event {
/**
* Create a new `MessageEvent`.
*
* @param {String} type The name of the event
* @param {Object} [options] A dictionary object that allows for setting
* attributes via object members of the same name
* @param {*} [options.data=null] The message content
*/
constructor(type, options = {}) {
super(type);
this[kData] = options.data === void 0 ? null : options.data;
}
/**
* @type {*}
*/
get data() {
return this[kData];
}
};
Object.defineProperty(MessageEvent.prototype, "data", { enumerable: true });
module.exports = {
CloseEvent,
ErrorEvent,
Event,
EventTarget: {
/**
* Register an event listener.
*
* @param {String} type A string representing the event type to listen for
* @param {(Function|Object)} handler The listener to add
* @param {Object} [options] An options object specifies characteristics about
* the event listener
* @param {Boolean} [options.once=false] A `Boolean` indicating that the
* listener should be invoked at most once after being added. If `true`,
* the listener would be automatically removed when invoked.
* @public
*/
addEventListener(type, handler, options = {}) {
for (const listener of this.listeners(type)) if (!options[kForOnEventAttribute] && listener[kListener] === handler && !listener[kForOnEventAttribute]) return;
let wrapper;
if (type === "message") wrapper = function onMessage(data, isBinary) {
const event = new MessageEvent("message", { data: isBinary ? data : data.toString() });
event[kTarget] = this;
callListener(handler, this, event);
};
else if (type === "close") wrapper = function onClose(code, message) {
const event = new CloseEvent("close", {
code,
reason: message.toString(),
wasClean: this._closeFrameReceived && this._closeFrameSent
});
event[kTarget] = this;
callListener(handler, this, event);
};
else if (type === "error") wrapper = function onError(error) {
const event = new ErrorEvent("error", {
error,
message: error.message
});
event[kTarget] = this;
callListener(handler, this, event);
};
else if (type === "open") wrapper = function onOpen() {
const event = new Event("open");
event[kTarget] = this;
callListener(handler, this, event);
};
else return;
wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
wrapper[kListener] = handler;
if (options.once) this.once(type, wrapper);
else this.on(type, wrapper);
},
/**
* Remove an event listener.
*
* @param {String} type A string representing the event type to remove
* @param {(Function|Object)} handler The listener to remove
* @public
*/
removeEventListener(type, handler) {
for (const listener of this.listeners(type)) if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {
this.removeListener(type, listener);
break;
}
}
},
MessageEvent
};
/**
* Call an event listener
*
* @param {(Function|Object)} listener The listener to call
* @param {*} thisArg The value to use as `this`` when calling the listener
* @param {Event} event The event to pass to the listener
* @private
*/
function callListener(listener, thisArg, event) {
if (typeof listener === "object" && listener.handleEvent) listener.handleEvent.call(listener, event);
else listener.call(thisArg, event);
}
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/extension.js
var require_extension = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const { tokenChars } = require_validation();
/**
* Adds an offer to the map of extension offers or a parameter to the map of
* parameters.
*
* @param {Object} dest The map of extension offers or parameters
* @param {String} name The extension or parameter name
* @param {(Object|Boolean|String)} elem The extension parameters or the
* parameter value
* @private
*/
function push(dest, name, elem) {
if (dest[name] === void 0) dest[name] = [elem];
else dest[name].push(elem);
}
/**
* Parses the `Sec-WebSocket-Extensions` header into an object.
*
* @param {String} header The field value of the header
* @return {Object} The parsed object
* @public
*/
function parse(header) {
const offers = Object.create(null);
let params = Object.create(null);
let mustUnescape = false;
let isEscaping = false;
let inQuotes = false;
let extensionName;
let paramName;
let start = -1;
let code = -1;
let end = -1;
let i = 0;
for (; i < header.length; i++) {
code = header.charCodeAt(i);
if (extensionName === void 0) if (end === -1 && tokenChars[code] === 1) {
if (start === -1) start = i;
} else if (i !== 0 && (code === 32 || code === 9)) {
if (end === -1 && start !== -1) end = i;
} else if (code === 59 || code === 44) {
if (start === -1) throw new SyntaxError(`Unexpected character at index ${i}`);
if (end === -1) end = i;
const name = header.slice(start, end);
if (code === 44) {
push(offers, name, params);
params = Object.create(null);
} else extensionName = name;
start = end = -1;
} else throw new SyntaxError(`Unexpected character at index ${i}`);
else if (paramName === void 0) if (end === -1 && tokenChars[code] === 1) {
if (start === -1) start = i;
} else if (code === 32 || code === 9) {
if (end === -1 && start !== -1) end = i;
} else if (code === 59 || code === 44) {
if (start === -1) throw new SyntaxError(`Unexpected character at index ${i}`);
if (end === -1) end = i;
push(params, header.slice(start, end), true);
if (code === 44) {
push(offers, extensionName, params);
params = Object.create(null);
extensionName = void 0;
}
start = end = -1;
} else if (code === 61 && start !== -1 && end === -1) {
paramName = header.slice(start, i);
start = end = -1;
} else throw new SyntaxError(`Unexpected character at index ${i}`);
else if (isEscaping) {
if (tokenChars[code] !== 1) throw new SyntaxError(`Unexpected character at index ${i}`);
if (start === -1) start = i;
else if (!mustUnescape) mustUnescape = true;
isEscaping = false;
} else if (inQuotes) if (tokenChars[code] === 1) {
if (start === -1) start = i;
} else if (code === 34 && start !== -1) {
inQuotes = false;
end = i;
} else if (code === 92) isEscaping = true;
else throw new SyntaxError(`Unexpected character at index ${i}`);
else if (code === 34 && header.charCodeAt(i - 1) === 61) inQuotes = true;
else if (end === -1 && tokenChars[code] === 1) {
if (start === -1) start = i;
} else if (start !== -1 && (code === 32 || code === 9)) {
if (end === -1) end = i;
} else if (code === 59 || code === 44) {
if (start === -1) throw new SyntaxError(`Unexpected character at index ${i}`);
if (end === -1) end = i;
let value = header.slice(start, end);
if (mustUnescape) {
value = value.replace(/\\/g, "");
mustUnescape = false;
}
push(params, paramName, value);
if (code === 44) {
push(offers, extensionName, params);
params = Object.create(null);
extensionName = void 0;
}
paramName = void 0;
start = end = -1;
} else throw new SyntaxError(`Unexpected character at index ${i}`);
}
if (start === -1 || inQuotes || code === 32 || code === 9) throw new SyntaxError("Unexpected end of input");
if (end === -1) end = i;
const token = header.slice(start, end);
if (extensionName === void 0) push(offers, token, params);
else {
if (paramName === void 0) push(params, token, true);
else if (mustUnescape) push(params, paramName, token.replace(/\\/g, ""));
else push(params, paramName, token);
push(offers, extensionName, params);
}
return offers;
}
/**
* Builds the `Sec-WebSocket-Extensions` header field value.
*
* @param {Object} extensions The map of extensions and parameters to format
* @return {String} A string representing the given object
* @public
*/
function format(extensions) {
return Object.keys(extensions).map((extension) => {
let configurations = extensions[extension];
if (!Array.isArray(configurations)) configurations = [configurations];
return configurations.map((params) => {
return [extension].concat(Object.keys(params).map((k) => {
let values = params[k];
if (!Array.isArray(values)) values = [values];
return values.map((v) => v === true ? k : `${k}=${v}`).join("; ");
})).join("; ");
}).join(", ");
}).join(", ");
}
module.exports = {
format,
parse
};
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/websocket.js
var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const EventEmitter$1 = __require("events");
const https = __require("https");
const http$1 = __require("http");
const net = __require("net");
const tls = __require("tls");
const { randomBytes, createHash: createHash$1 } = __require("crypto");
const { Duplex: Duplex$2, Readable } = __require("stream");
const { URL: URL$1 } = __require("url");
const PerMessageDeflate = require_permessage_deflate();
const Receiver = require_receiver();
const Sender = require_sender();
const { isBlob } = require_validation();
const { BINARY_TYPES, CLOSE_TIMEOUT, EMPTY_BUFFER, GUID, kForOnEventAttribute, kListener, kStatusCode, kWebSocket, NOOP } = require_constants();
const { EventTarget: { addEventListener, removeEventListener } } = require_event_target();
const { format, parse } = require_extension();
const { toBuffer } = require_buffer_util();
const kAborted = Symbol("kAborted");
const protocolVersions = [8, 13];
const readyStates = [
"CONNECTING",
"OPEN",
"CLOSING",
"CLOSED"
];
const subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
/**
* Class representing a WebSocket.
*
* @extends EventEmitter
*/
var WebSocket = class WebSocket extends EventEmitter$1 {
/**
* Create a new `WebSocket`.
*
* @param {(String|URL)} address The URL to which to connect
* @param {(String|String[])} [protocols] The subprotocols
* @param {Object} [options] Connection options
*/
constructor(address, protocols, options) {
super();
this._binaryType = BINARY_TYPES[0];
this._closeCode = 1006;
this._closeFrameReceived = false;
this._closeFrameSent = false;
this._closeMessage = EMPTY_BUFFER;
this._closeTimer = null;
this._errorEmitted = false;
this._extensions = {};
this._paused = false;
this._protocol = "";
this._readyState = WebSocket.CONNECTING;
this._receiver = null;
this._sender = null;
this._socket = null;
if (address !== null) {
this._bufferedAmount = 0;
this._isServer = false;
this._redirects = 0;
if (protocols === void 0) protocols = [];
else if (!Array.isArray(protocols)) if (typeof protocols === "object" && protocols !== null) {
options = protocols;
protocols = [];
} else protocols = [protocols];
initAsClient(this, address, protocols, options);
} else {
this._autoPong = options.autoPong;
this._closeTimeout = options.closeTimeout;
this._isServer = true;
}
}
/**
* For historical reasons, the custom "nodebuffer" type is used by the default
* instead of "blob".
*
* @type {String}
*/
get binaryType() {
return this._binaryType;
}
set binaryType(type) {
if (!BINARY_TYPES.includes(type)) return;
this._binaryType = type;
if (this._receiver) this._receiver._binaryType = type;
}
/**
* @type {Number}
*/
get bufferedAmount() {
if (!this._socket) return this._bufferedAmount;
return this._socket._writableState.length + this._sender._bufferedBytes;
}
/**
* @type {String}
*/
get extensions() {
return Object.keys(this._extensions).join();
}
/**
* @type {Boolean}
*/
get isPaused() {
return this._paused;
}
/**
* @type {Function}
*/
/* istanbul ignore next */
get onclose() {
return null;
}
/**
* @type {Function}
*/
/* istanbul ignore next */
get onerror() {
return null;
}
/**
* @type {Function}
*/
/* istanbul ignore next */
get onopen() {
return null;
}
/**
* @type {Function}
*/
/* istanbul ignore next */
get onmessage() {
return null;
}
/**
* @type {String}
*/
get protocol() {
return this._protocol;
}
/**
* @type {Number}
*/
get readyState() {
return this._readyState;
}
/**
* @type {String}
*/
get url() {
return this._url;
}
/**
* Set up the socket and the internal resources.
*
* @param {Duplex} socket The network socket between the server and client
* @param {Buffer} head The first packet of the upgraded stream
* @param {Object} options Options object
* @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether
* any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
* multiple times in the same tick
* @param {Function} [options.generateMask] The function used to generate the
* masking key
* @param {Number} [options.maxBufferedChunks=0] The maximum number of
* buffered data chunks
* @param {Number} [options.maxFragments=0] The maximum number of message
* fragments
* @param {Number} [options.maxPayload=0] The maximum allowed message size
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
* not to skip UTF-8 validation for text and close messages
* @private
*/
setSocket(socket, head, options) {
const receiver = new Receiver({
allowSynchronousEvents: options.allowSynchronousEvents,
binaryType: this.binaryType,
extensions: this._extensions,
isServer: this._isServer,
maxBufferedChunks: options.maxBufferedChunks,
maxFragments: options.maxFragments,
maxPayload: options.maxPayload,
skipUTF8Validation: options.skipUTF8Validation
});
const sender = new Sender(socket, this._extensions, options.generateMask);
this._receiver = receiver;
this._sender = sender;
this._socket = socket;
receiver[kWebSocket] = this;
sender[kWebSocket] = this;
socket[kWebSocket] = this;
receiver.on("conclude", receiverOnConclude);
receiver.on("drain", receiverOnDrain);
receiver.on("error", receiverOnError);
receiver.on("message", receiverOnMessage);
receiver.on("ping", receiverOnPing);
receiver.on("pong", receiverOnPong);
sender.onerror = senderOnError;
if (socket.setTimeout) socket.setTimeout(0);
if (socket.setNoDelay) socket.setNoDelay();
if (head.length > 0) socket.unshift(head);
socket.on("close", socketOnClose);
socket.on("data", socketOnData);
socket.on("end", socketOnEnd);
socket.on("error", socketOnError);
this._readyState = WebSocket.OPEN;
this.emit("open");
}
/**
* Emit the `'close'` event.
*
* @private
*/
emitClose() {
if (!this._socket) {
this._readyState = WebSocket.CLOSED;
this.emit("close", this._closeCode, this._closeMessage);
return;
}
if (this._extensions[PerMessageDeflate.extensionName]) this._extensions[PerMessageDeflate.extensionName].cleanup();
this._receiver.removeAllListeners();
this._readyState = WebSocket.CLOSED;
this.emit("close", this._closeCode, this._closeMessage);
}
/**
* Start a closing handshake.
*
* +----------+ +-----------+ +----------+
* - - -|ws.close()|-->|close frame|-->|ws.close()|- - -
* | +----------+ +-----------+ +----------+ |
* +----------+ +-----------+ |
* CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING
* +----------+ +-----------+ |
* | | | +---+ |
* +------------------------+-->|fin| - - - -
* | +---+ | +---+
* - - - - -|fin|<---------------------+
* +---+
*
* @param {Number} [code] Status code explaining why the connection is closing
* @param {(String|Buffer)} [data] The reason why the connection is
* closing
* @public
*/
close(code, data) {
if (this.readyState === WebSocket.CLOSED) return;
if (this.readyState === WebSocket.CONNECTING) {
abortHandshake(this, this._req, "WebSocket was closed before the connection was established");
return;
}
if (this.readyState === WebSocket.CLOSING) {
if (this._closeFrameSent && (this._closeFrameReceived || this._receiver._writableState.errorEmitted)) this._socket.end();
return;
}
this._readyState = WebSocket.CLOSING;
this._sender.close(code, data, !this._isServer, (err) => {
if (err) return;
this._closeFrameSent = true;
if (this._closeFrameReceived || this._receiver._writableState.errorEmitted) this._socket.end();
});
setCloseTimer(this);
}
/**
* Pause the socket.
*
* @public
*/
pause() {
if (this.readyState === WebSocket.CONNECTING || this.readyState === WebSocket.CLOSED) return;
this._paused = true;
this._socket.pause();
}
/**
* Send a ping.
*
* @param {*} [data] The data to send
* @param {Boolean} [mask] Indicates whether or not to mask `data`
* @param {Function} [cb] Callback which is executed when the ping is sent
* @public
*/
ping(data, mask, cb) {
if (this.readyState === WebSocket.CONNECTING) throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
if (typeof data === "function") {
cb = data;
data = mask = void 0;
} else if (typeof mask === "function") {
cb = mask;
mask = void 0;
}
if (typeof data === "number") data = data.toString();
if (this.readyState !== WebSocket.OPEN) {
sendAfterClose(this, data, cb);
return;
}
if (mask === void 0) mask = !this._isServer;
this._sender.ping(data || EMPTY_BUFFER, mask, cb);
}
/**
* Send a pong.
*
* @param {*} [data] The data to send
* @param {Boolean} [mask] Indicates whether or not to mask `data`
* @param {Function} [cb] Callback which is executed when the pong is sent
* @public
*/
pong(data, mask, cb) {
if (this.readyState === WebSocket.CONNECTING) throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
if (typeof data === "function") {
cb = data;
data = mask = void 0;
} else if (typeof mask === "function") {
cb = mask;
mask = void 0;
}
if (typeof data === "number") data = data.toString();
if (this.readyState !== WebSocket.OPEN) {
sendAfterClose(this, data, cb);
return;
}
if (mask === void 0) mask = !this._isServer;
this._sender.pong(data || EMPTY_BUFFER, mask, cb);
}
/**
* Resume the socket.
*
* @public
*/
resume() {
if (this.readyState === WebSocket.CONNECTING || this.readyState === WebSocket.CLOSED) return;
this._paused = false;
if (!this._receiver._writableState.needDrain) this._socket.resume();
}
/**
* Send a data message.
*
* @param {*} data The message to send
* @param {Object} [options] Options object
* @param {Boolean} [options.binary] Specifies whether `data` is binary or
* text
* @param {Boolean} [options.compress] Specifies whether or not to compress
* `data`
* @param {Boolean} [options.fin=true] Specifies whether the fragment is the
* last one
* @param {Boolean} [options.mask] Specifies whether or not to mask `data`
* @param {Function} [cb] Callback which is executed when data is written out
* @public
*/
send(data, options, cb) {
if (this.readyState === WebSocket.CONNECTING) throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
if (typeof options === "function") {
cb = options;
options = {};
}
if (typeof data === "number") data = data.toString();
if (this.readyState !== WebSocket.OPEN) {
sendAfterClose(this, data, cb);
return;
}
const opts = {
binary: typeof data !== "string",
mask: !this._isServer,
compress: true,
fin: true,
...options
};
if (!this._extensions[PerMessageDeflate.extensionName]) opts.compress = false;
this._sender.send(data || EMPTY_BUFFER, opts, cb);
}
/**
* Forcibly close the connection.
*
* @public
*/
terminate() {
if (this.readyState === WebSocket.CLOSED) return;
if (this.readyState === WebSocket.CONNECTING) {
abortHandshake(this, this._req, "WebSocket was closed before the connection was established");
return;
}
if (this._socket) {
this._readyState = WebSocket.CLOSING;
this._socket.destroy();
}
}
};
/**
* @constant {Number} CONNECTING
* @memberof WebSocket
*/
Object.defineProperty(WebSocket, "CONNECTING", {
enumerable: true,
value: readyStates.indexOf("CONNECTING")
});
/**
* @constant {Number} CONNECTING
* @memberof WebSocket.prototype
*/
Object.defineProperty(WebSocket.prototype, "CONNECTING", {
enumerable: true,
value: readyStates.indexOf("CONNECTING")
});
/**
* @constant {Number} OPEN
* @memberof WebSocket
*/
Object.defineProperty(WebSocket, "OPEN", {
enumerable: true,
value: readyStates.indexOf("OPEN")
});
/**
* @constant {Number} OPEN
* @memberof WebSocket.prototype
*/
Object.defineProperty(WebSocket.prototype, "OPEN", {
enumerable: true,
value: readyStates.indexOf("OPEN")
});
/**
* @constant {Number} CLOSING
* @memberof WebSocket
*/
Object.defineProperty(WebSocket, "CLOSING", {
enumerable: true,
value: readyStates.indexOf("CLOSING")
});
/**
* @constant {Number} CLOSING
* @memberof WebSocket.prototype
*/
Object.defineProperty(WebSocket.prototype, "CLOSING", {
enumerable: true,
value: readyStates.indexOf("CLOSING")
});
/**
* @constant {Number} CLOSED
* @memberof WebSocket
*/
Object.defineProperty(WebSocket, "CLOSED", {
enumerable: true,
value: readyStates.indexOf("CLOSED")
});
/**
* @constant {Number} CLOSED
* @memberof WebSocket.prototype
*/
Object.defineProperty(WebSocket.prototype, "CLOSED", {
enumerable: true,
value: readyStates.indexOf("CLOSED")
});
[
"binaryType",
"bufferedAmount",
"extensions",
"isPaused",
"protocol",
"readyState",
"url"
].forEach((property) => {
Object.defineProperty(WebSocket.prototype, property, { enumerable: true });
});
[
"open",
"error",
"close",
"message"
].forEach((method) => {
Object.defineProperty(WebSocket.prototype, `on${method}`, {
enumerable: true,
get() {
for (const listener of this.listeners(method)) if (listener[kForOnEventAttribute]) return listener[kListener];
return null;
},
set(handler) {
for (const listener of this.listeners(method)) if (listener[kForOnEventAttribute]) {
this.removeListener(method, listener);
break;
}
if (typeof handler !== "function") return;
this.addEventListener(method, handler, { [kForOnEventAttribute]: true });
}
});
});
WebSocket.prototype.addEventListener = addEventListener;
WebSocket.prototype.removeEventListener = removeEventListener;
module.exports = WebSocket;
/**
* Initialize a WebSocket client.
*
* @param {WebSocket} websocket The client to initialize
* @param {(String|URL)} address The URL to which to connect
* @param {Array} protocols The subprotocols
* @param {Object} [options] Connection options
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any
* of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple
* times in the same tick
* @param {Boolean} [options.autoPong=true] Specifies whether or not to
* automatically send a pong in response to a ping
* @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait
* for the closing handshake to finish after `websocket.close()` is called
* @param {Function} [options.finishRequest] A function which can be used to
* customize the headers of each http request before it is sent
* @param {Boolean} [options.followRedirects=false] Whether or not to follow
* redirects
* @param {Function} [options.generateMask] The function used to generate the
* masking key
* @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
* handshake request
* @param {Number} [options.maxBufferedChunks=262144] The maximum number of
* buffered data chunks
* @param {Number} [options.maxFragments=16384] The maximum number of message
* fragments
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
* size
* @param {Number} [options.maxRedirects=10] The maximum number of redirects
* allowed
* @param {String} [options.origin] Value of the `Origin` or
* `Sec-WebSocket-Origin` header
* @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
* permessage-deflate
* @param {Number} [options.protocolVersion=13] Value of the
* `Sec-WebSocket-Version` header
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
* not to skip UTF-8 validation for text and close messages
* @private
*/
function initAsClient(websocket, address, protocols, options) {
const opts = {
allowSynchronousEvents: true,
autoPong: true,
closeTimeout: CLOSE_TIMEOUT,
protocolVersion: protocolVersions[1],
maxBufferedChunks: 256 * 1024,
maxFragments: 16 * 1024,
maxPayload: 100 * 1024 * 1024,
skipUTF8Validation: false,
perMessageDeflate: true,
followRedirects: false,
maxRedirects: 10,
...options,
socketPath: void 0,
hostname: void 0,
protocol: void 0,
timeout: void 0,
method: "GET",
host: void 0,
path: void 0,
port: void 0
};
websocket._autoPong = opts.autoPong;
websocket._closeTimeout = opts.closeTimeout;
if (!protocolVersions.includes(opts.protocolVersion)) throw new RangeError(`Unsupported protocol version: ${opts.protocolVersion} (supported versions: ${protocolVersions.join(", ")})`);
let parsedUrl;
if (address instanceof URL$1) parsedUrl = address;
else try {
parsedUrl = new URL$1(address);
} catch {
throw new SyntaxError(`Invalid URL: ${address}`);
}
if (parsedUrl.protocol === "http:") parsedUrl.protocol = "ws:";
else if (parsedUrl.protocol === "https:") parsedUrl.protocol = "wss:";
websocket._url = parsedUrl.href;
const isSecure = parsedUrl.protocol === "wss:";
const isIpcUrl = parsedUrl.protocol === "ws+unix:";
let invalidUrlMessage;
if (parsedUrl.protocol !== "ws:" && !isSecure && !isIpcUrl) invalidUrlMessage = "The URL's protocol must be one of \"ws:\", \"wss:\", \"http:\", \"https:\", or \"ws+unix:\"";
else if (isIpcUrl && !parsedUrl.pathname) invalidUrlMessage = "The URL's pathname is empty";
else if (parsedUrl.hash) invalidUrlMessage = "The URL contains a fragment identifier";
if (invalidUrlMessage) {
const err = new SyntaxError(invalidUrlMessage);
if (websocket._redirects === 0) throw err;
else {
emitErrorAndClose(websocket, err);
return;
}
}
const defaultPort = isSecure ? 443 : 80;
const key = randomBytes(16).toString("base64");
const request = isSecure ? https.request : http$1.request;
const protocolSet = /* @__PURE__ */ new Set();
let perMessageDeflate;
opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect);
opts.defaultPort = opts.defaultPort || defaultPort;
opts.port = parsedUrl.port || defaultPort;
opts.host = parsedUrl.hostname.startsWith("[") ? parsedUrl.hostname.slice(1, -1) : parsedUrl.hostname;
opts.headers = {
...opts.headers,
"Sec-WebSocket-Version": opts.protocolVersion,
"Sec-WebSocket-Key": key,
Connection: "Upgrade",
Upgrade: "websocket"
};
opts.path = parsedUrl.pathname + parsedUrl.search;
opts.timeout = opts.handshakeTimeout;
if (opts.perMessageDeflate) {
perMessageDeflate = new PerMessageDeflate({
...opts.perMessageDeflate,
isServer: false,
maxPayload: opts.maxPayload
});
opts.headers["Sec-WebSocket-Extensions"] = format({ [PerMessageDeflate.extensionName]: perMessageDeflate.offer() });
}
if (protocols.length) {
for (const protocol of protocols) {
if (typeof protocol !== "string" || !subprotocolRegex.test(protocol) || protocolSet.has(protocol)) throw new SyntaxError("An invalid or duplicated subprotocol was specified");
protocolSet.add(protocol);
}
opts.headers["Sec-WebSocket-Protocol"] = protocols.join(",");
}
if (opts.origin) if (opts.protocolVersion < 13) opts.headers["Sec-WebSocket-Origin"] = opts.origin;
else opts.headers.Origin = opts.origin;
if (parsedUrl.username || parsedUrl.password) opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
if (isIpcUrl) {
const parts = opts.path.split(":");
opts.socketPath = parts[0];
opts.path = parts[1];
}
let req;
if (opts.followRedirects) {
if (websocket._redirects === 0) {
websocket._originalIpc = isIpcUrl;
websocket._originalSecure = isSecure;
websocket._originalHostOrSocketPath = isIpcUrl ? opts.socketPath : parsedUrl.host;
const headers = options && options.headers;
options = {
...options,
headers: {}
};
if (headers) for (const [key, value] of Object.entries(headers)) options.headers[key.toLowerCase()] = value;
} else if (websocket.listenerCount("redirect") === 0) {
const isSameHost = isIpcUrl ? websocket._originalIpc ? opts.socketPath === websocket._originalHostOrSocketPath : false : websocket._originalIpc ? false : parsedUrl.host === websocket._originalHostOrSocketPath;
if (!isSameHost || websocket._originalSecure && !isSecure) {
delete opts.headers.authorization;
delete opts.headers.cookie;
if (!isSameHost) delete opts.headers.host;
opts.auth = void 0;
}
}
if (opts.auth && !options.headers.authorization) options.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64");
req = websocket._req = request(opts);
if (websocket._redirects) websocket.emit("redirect", websocket.url, req);
} else req = websocket._req = request(opts);
if (opts.timeout) req.on("timeout", () => {
abortHandshake(websocket, req, "Opening handshake has timed out");
});
req.on("error", (err) => {
if (req === null || req[kAborted]) return;
req = websocket._req = null;
emitErrorAndClose(websocket, err);
});
req.on("response", (res) => {
const location = res.headers.location;
const statusCode = res.statusCode;
if (location && opts.followRedirects && statusCode >= 300 && statusCode < 400) {
if (++websocket._redirects > opts.maxRedirects) {
abortHandshake(websocket, req, "Maximum redirects exceeded");
return;
}
req.abort();
let addr;
try {
addr = new URL$1(location, address);
} catch (e) {
emitErrorAndClose(websocket, /* @__PURE__ */ new SyntaxError(`Invalid URL: ${location}`));
return;
}
initAsClient(websocket, addr, protocols, options);
} else if (!websocket.emit("unexpected-response", req, res)) abortHandshake(websocket, req, `Unexpected server response: ${res.statusCode}`);
});
req.on("upgrade", (res, socket, head) => {
websocket.emit("upgrade", res);
if (websocket.readyState !== WebSocket.CONNECTING) return;
req = websocket._req = null;
const upgrade = res.headers.upgrade;
if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
abortHandshake(websocket, socket, "Invalid Upgrade header");
return;
}
const digest = createHash$1("sha1").update(key + GUID).digest("base64");
if (res.headers["sec-websocket-accept"] !== digest) {
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
return;
}
const serverProt = res.headers["sec-websocket-protocol"];
let protError;
if (serverProt !== void 0) {
if (!protocolSet.size) protError = "Server sent a subprotocol but none was requested";
else if (!protocolSet.has(serverProt)) protError = "Server sent an invalid subprotocol";
} else if (protocolSet.size) protError = "Server sent no subprotocol";
if (protError) {
abortHandshake(websocket, socket, protError);
return;
}
if (serverProt) websocket._protocol = serverProt;
const secWebSocketExtensions = res.headers["sec-websocket-extensions"];
if (secWebSocketExtensions !== void 0) {
if (!perMessageDeflate) {
abortHandshake(websocket, socket, "Server sent a Sec-WebSocket-Extensions header but no extension was requested");
return;
}
let extensions;
try {
extensions = parse(secWebSocketExtensions);
} catch (err) {
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Extensions header");
return;
}
const extensionNames = Object.keys(extensions);
if (extensionNames.length !== 1 || extensionNames[0] !== PerMessageDeflate.extensionName) {
abortHandshake(websocket, socket, "Server indicated an extension that was not requested");
return;
}
try {
perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
} catch (err) {
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Extensions header");
return;
}
websocket._extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
}
websocket.setSocket(socket, head, {
allowSynchronousEvents: opts.allowSynchronousEvents,
generateMask: opts.generateMask,
maxBufferedChunks: opts.maxBufferedChunks,
maxFragments: opts.maxFragments,
maxPayload: opts.maxPayload,
skipUTF8Validation: opts.skipUTF8Validation
});
});
if (opts.finishRequest) opts.finishRequest(req, websocket);
else req.end();
}
/**
* Emit the `'error'` and `'close'` events.
*
* @param {WebSocket} websocket The WebSocket instance
* @param {Error} The error to emit
* @private
*/
function emitErrorAndClose(websocket, err) {
websocket._readyState = WebSocket.CLOSING;
websocket._errorEmitted = true;
websocket.emit("error", err);
websocket.emitClose();
}
/**
* Create a `net.Socket` and initiate a connection.
*
* @param {Object} options Connection options
* @return {net.Socket} The newly created socket used to start the connection
* @private
*/
function netConnect(options) {
options.path = options.socketPath;
return net.connect(options);
}
/**
* Create a `tls.TLSSocket` and initiate a connection.
*
* @param {Object} options Connection options
* @return {tls.TLSSocket} The newly created socket used to start the connection
* @private
*/
function tlsConnect(options) {
options.path = void 0;
if (!options.servername && options.servername !== "") options.servername = net.isIP(options.host) ? "" : options.host;
return tls.connect(options);
}
/**
* Abort the handshake and emit an error.
*
* @param {WebSocket} websocket The WebSocket instance
* @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to
* abort or the socket to destroy
* @param {String} message The error message
* @private
*/
function abortHandshake(websocket, stream, message) {
websocket._readyState = WebSocket.CLOSING;
const err = new Error(message);
Error.captureStackTrace(err, abortHandshake);
if (stream.setHeader) {
stream[kAborted] = true;
stream.abort();
if (stream.socket && !stream.socket.destroyed) stream.socket.destroy();
process.nextTick(emitErrorAndClose, websocket, err);
} else {
stream.destroy(err);
stream.once("error", websocket.emit.bind(websocket, "error"));
stream.once("close", websocket.emitClose.bind(websocket));
}
}
/**
* Handle cases where the `ping()`, `pong()`, or `send()` methods are called
* when the `readyState` attribute is `CLOSING` or `CLOSED`.
*
* @param {WebSocket} websocket The WebSocket instance
* @param {*} [data] The data to send
* @param {Function} [cb] Callback
* @private
*/
function sendAfterClose(websocket, data, cb) {
if (data) {
const length = isBlob(data) ? data.size : toBuffer(data).length;
if (websocket._socket) websocket._sender._bufferedBytes += length;
else websocket._bufferedAmount += length;
}
if (cb) {
const err = /* @__PURE__ */ new Error(`WebSocket is not open: readyState ${websocket.readyState} (${readyStates[websocket.readyState]})`);
process.nextTick(cb, err);
}
}
/**
* The listener of the `Receiver` `'conclude'` event.
*
* @param {Number} code The status code
* @param {Buffer} reason The reason for closing
* @private
*/
function receiverOnConclude(code, reason) {
const websocket = this[kWebSocket];
websocket._closeFrameReceived = true;
websocket._closeMessage = reason;
websocket._closeCode = code;
if (websocket._socket[kWebSocket] === void 0) return;
websocket._socket.removeListener("data", socketOnData);
process.nextTick(resume, websocket._socket);
if (code === 1005) websocket.close();
else websocket.close(code, reason);
}
/**
* The listener of the `Receiver` `'drain'` event.
*
* @private
*/
function receiverOnDrain() {
const websocket = this[kWebSocket];
if (!websocket.isPaused) websocket._socket.resume();
}
/**
* The listener of the `Receiver` `'error'` event.
*
* @param {(RangeError|Error)} err The emitted error
* @private
*/
function receiverOnError(err) {
const websocket = this[kWebSocket];
if (websocket._socket[kWebSocket] !== void 0) {
websocket._socket.removeListener("data", socketOnData);
process.nextTick(resume, websocket._socket);
websocket.close(err[kStatusCode]);
}
if (!websocket._errorEmitted) {
websocket._errorEmitted = true;
websocket.emit("error", err);
}
}
/**
* The listener of the `Receiver` `'finish'` event.
*
* @private
*/
function receiverOnFinish() {
this[kWebSocket].emitClose();
}
/**
* The listener of the `Receiver` `'message'` event.
*
* @param {Buffer|ArrayBuffer|Buffer[])} data The message
* @param {Boolean} isBinary Specifies whether the message is binary or not
* @private
*/
function receiverOnMessage(data, isBinary) {
this[kWebSocket].emit("message", data, isBinary);
}
/**
* The listener of the `Receiver` `'ping'` event.
*
* @param {Buffer} data The data included in the ping frame
* @private
*/
function receiverOnPing(data) {
const websocket = this[kWebSocket];
if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);
websocket.emit("ping", data);
}
/**
* The listener of the `Receiver` `'pong'` event.
*
* @param {Buffer} data The data included in the pong frame
* @private
*/
function receiverOnPong(data) {
this[kWebSocket].emit("pong", data);
}
/**
* Resume a readable stream
*
* @param {Readable} stream The readable stream
* @private
*/
function resume(stream) {
stream.resume();
}
/**
* The `Sender` error event handler.
*
* @param {Error} The error
* @private
*/
function senderOnError(err) {
const websocket = this[kWebSocket];
if (websocket.readyState === WebSocket.CLOSED) return;
if (websocket.readyState === WebSocket.OPEN) {
websocket._readyState = WebSocket.CLOSING;
setCloseTimer(websocket);
}
this._socket.end();
if (!websocket._errorEmitted) {
websocket._errorEmitted = true;
websocket.emit("error", err);
}
}
/**
* Set a timer to destroy the underlying raw socket of a WebSocket.
*
* @param {WebSocket} websocket The WebSocket instance
* @private
*/
function setCloseTimer(websocket) {
websocket._closeTimer = setTimeout(websocket._socket.destroy.bind(websocket._socket), websocket._closeTimeout);
}
/**
* The listener of the socket `'close'` event.
*
* @private
*/
function socketOnClose() {
const websocket = this[kWebSocket];
this.removeListener("close", socketOnClose);
this.removeListener("data", socketOnData);
this.removeListener("end", socketOnEnd);
websocket._readyState = WebSocket.CLOSING;
if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && this._readableState.length !== 0) {
const chunk = this.read(this._readableState.length);
websocket._receiver.write(chunk);
}
websocket._receiver.end();
this[kWebSocket] = void 0;
clearTimeout(websocket._closeTimer);
if (websocket._receiver._writableState.finished || websocket._receiver._writableState.errorEmitted) websocket.emitClose();
else {
websocket._receiver.on("error", receiverOnFinish);
websocket._receiver.on("finish", receiverOnFinish);
}
}
/**
* The listener of the socket `'data'` event.
*
* @param {Buffer} chunk A chunk of data
* @private
*/
function socketOnData(chunk) {
if (!this[kWebSocket]._receiver.write(chunk)) this.pause();
}
/**
* The listener of the socket `'end'` event.
*
* @private
*/
function socketOnEnd() {
const websocket = this[kWebSocket];
websocket._readyState = WebSocket.CLOSING;
websocket._receiver.end();
this.end();
}
/**
* The listener of the socket `'error'` event.
*
* @private
*/
function socketOnError() {
const websocket = this[kWebSocket];
this.removeListener("error", socketOnError);
this.on("error", NOOP);
if (websocket) {
websocket._readyState = WebSocket.CLOSING;
this.destroy();
}
}
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/stream.js
var require_stream = /* @__PURE__ */ __commonJSMin(((exports, module) => {
require_websocket();
const { Duplex: Duplex$1 } = __require("stream");
/**
* Emits the `'close'` event on a stream.
*
* @param {Duplex} stream The stream.
* @private
*/
function emitClose(stream) {
stream.emit("close");
}
/**
* The listener of the `'end'` event.
*
* @private
*/
function duplexOnEnd() {
if (!this.destroyed && this._writableState.finished) this.destroy();
}
/**
* The listener of the `'error'` event.
*
* @param {Error} err The error
* @private
*/
function duplexOnError(err) {
this.removeListener("error", duplexOnError);
this.destroy();
if (this.listenerCount("error") === 0) this.emit("error", err);
}
/**
* Wraps a `WebSocket` in a duplex stream.
*
* @param {WebSocket} ws The `WebSocket` to wrap
* @param {Object} [options] The options for the `Duplex` constructor
* @return {Duplex} The duplex stream
* @public
*/
function createWebSocketStream(ws, options) {
let terminateOnDestroy = true;
const duplex = new Duplex$1({
...options,
autoDestroy: false,
emitClose: false,
objectMode: false,
writableObjectMode: false
});
ws.on("message", function message(msg, isBinary) {
const data = !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;
if (!duplex.push(data)) ws.pause();
});
ws.once("error", function error(err) {
if (duplex.destroyed) return;
terminateOnDestroy = false;
duplex.destroy(err);
});
ws.once("close", function close() {
if (duplex.destroyed) return;
duplex.push(null);
});
duplex._destroy = function(err, callback) {
if (ws.readyState === ws.CLOSED) {
callback(err);
process.nextTick(emitClose, duplex);
return;
}
let called = false;
ws.once("error", function error(err) {
called = true;
callback(err);
});
ws.once("close", function close() {
if (!called) callback(err);
process.nextTick(emitClose, duplex);
});
if (terminateOnDestroy) ws.terminate();
};
duplex._final = function(callback) {
if (ws.readyState === ws.CONNECTING) {
ws.once("open", function open() {
duplex._final(callback);
});
return;
}
if (ws._socket === null) return;
if (ws._socket._writableState.finished) {
callback();
if (duplex._readableState.endEmitted) duplex.destroy();
} else {
ws._socket.once("finish", function finish() {
callback();
});
ws.close();
}
};
duplex._read = function() {
if (ws.isPaused) ws.resume();
};
duplex._write = function(chunk, encoding, callback) {
if (ws.readyState === ws.CONNECTING) {
ws.once("open", function open() {
duplex._write(chunk, encoding, callback);
});
return;
}
ws.send(chunk, callback);
};
duplex.on("end", duplexOnEnd);
duplex.on("error", duplexOnError);
return duplex;
}
module.exports = createWebSocketStream;
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/subprotocol.js
var require_subprotocol = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const { tokenChars } = require_validation();
/**
* Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.
*
* @param {String} header The field value of the header
* @return {Set} The subprotocol names
* @public
*/
function parse(header) {
const protocols = /* @__PURE__ */ new Set();
let start = -1;
let end = -1;
let i = 0;
for (; i < header.length; i++) {
const code = header.charCodeAt(i);
if (end === -1 && tokenChars[code] === 1) {
if (start === -1) start = i;
} else if (i !== 0 && (code === 32 || code === 9)) {
if (end === -1 && start !== -1) end = i;
} else if (code === 44) {
if (start === -1) throw new SyntaxError(`Unexpected character at index ${i}`);
if (end === -1) end = i;
const protocol = header.slice(start, end);
if (protocols.has(protocol)) throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
protocols.add(protocol);
start = end = -1;
} else throw new SyntaxError(`Unexpected character at index ${i}`);
}
if (start === -1 || end !== -1) throw new SyntaxError("Unexpected end of input");
const protocol = header.slice(start, i);
if (protocols.has(protocol)) throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
protocols.add(protocol);
return protocols;
}
module.exports = { parse };
}));
//#endregion
//#region node_modules/.pnpm/ws@8.21.1_bufferutil@4.1.0_utf-8-validate@5.0.10/node_modules/ws/lib/websocket-server.js
var require_websocket_server = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const EventEmitter = __require("events");
const http = __require("http");
const { Duplex } = __require("stream");
const { createHash } = __require("crypto");
const extension = require_extension();
const PerMessageDeflate = require_permessage_deflate();
const subprotocol = require_subprotocol();
const WebSocket = require_websocket();
const { CLOSE_TIMEOUT, GUID, kWebSocket } = require_constants();
const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
const RUNNING = 0;
const CLOSING = 1;
const CLOSED = 2;
/**
* Class representing a WebSocket server.
*
* @extends EventEmitter
*/
var WebSocketServer = class extends EventEmitter {
/**
* Create a `WebSocketServer` instance.
*
* @param {Object} options Configuration options
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
* any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
* multiple times in the same tick
* @param {Boolean} [options.autoPong=true] Specifies whether or not to
* automatically send a pong in response to a ping
* @param {Number} [options.backlog=511] The maximum length of the queue of
* pending connections
* @param {Boolean} [options.clientTracking=true] Specifies whether or not to
* track clients
* @param {Number} [options.closeTimeout=30000] Duration in milliseconds to
* wait for the closing handshake to finish after `websocket.close()` is
* called
* @param {Function} [options.handleProtocols] A hook to handle protocols
* @param {String} [options.host] The hostname where to bind the server
* @param {Number} [options.maxBufferedChunks=262144] The maximum number of
* buffered data chunks
* @param {Number} [options.maxFragments=16384] The maximum number of message
* fragments
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
* size
* @param {Boolean} [options.noServer=false] Enable no server mode
* @param {String} [options.path] Accept only connections matching this path
* @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
* permessage-deflate
* @param {Number} [options.port] The port where to bind the server
* @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
* server to use
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
* not to skip UTF-8 validation for text and close messages
* @param {Function} [options.verifyClient] A hook to reject connections
* @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`
* class to use. It must be the `WebSocket` class or class that extends it
* @param {Function} [callback] A listener for the `listening` event
*/
constructor(options, callback) {
super();
options = {
allowSynchronousEvents: true,
autoPong: true,
maxBufferedChunks: 256 * 1024,
maxFragments: 16 * 1024,
maxPayload: 100 * 1024 * 1024,
skipUTF8Validation: false,
perMessageDeflate: false,
handleProtocols: null,
clientTracking: true,
closeTimeout: CLOSE_TIMEOUT,
verifyClient: null,
noServer: false,
backlog: null,
server: null,
host: null,
path: null,
port: null,
WebSocket,
...options
};
if (options.port == null && !options.server && !options.noServer || options.port != null && (options.server || options.noServer) || options.server && options.noServer) throw new TypeError("One and only one of the \"port\", \"server\", or \"noServer\" options must be specified");
if (options.port != null) {
this._server = http.createServer((req, res) => {
const body = http.STATUS_CODES[426];
res.writeHead(426, {
"Content-Length": body.length,
"Content-Type": "text/plain"
});
res.end(body);
});
this._server.listen(options.port, options.host, options.backlog, callback);
} else if (options.server) this._server = options.server;
if (this._server) {
const emitConnection = this.emit.bind(this, "connection");
this._removeListeners = addListeners(this._server, {
listening: this.emit.bind(this, "listening"),
error: this.emit.bind(this, "error"),
upgrade: (req, socket, head) => {
this.handleUpgrade(req, socket, head, emitConnection);
}
});
}
if (options.perMessageDeflate === true) options.perMessageDeflate = {};
if (options.clientTracking) {
this.clients = /* @__PURE__ */ new Set();
this._shouldEmitClose = false;
}
this.options = options;
this._state = RUNNING;
}
/**
* Returns the bound address, the address family name, and port of the server
* as reported by the operating system if listening on an IP socket.
* If the server is listening on a pipe or UNIX domain socket, the name is
* returned as a string.
*
* @return {(Object|String|null)} The address of the server
* @public
*/
address() {
if (this.options.noServer) throw new Error("The server is operating in \"noServer\" mode");
if (!this._server) return null;
return this._server.address();
}
/**
* Stop the server from accepting new connections and emit the `'close'` event
* when all existing connections are closed.
*
* @param {Function} [cb] A one-time listener for the `'close'` event
* @public
*/
close(cb) {
if (this._state === CLOSED) {
if (cb) this.once("close", () => {
cb(/* @__PURE__ */ new Error("The server is not running"));
});
process.nextTick(emitClose, this);
return;
}
if (cb) this.once("close", cb);
if (this._state === CLOSING) return;
this._state = CLOSING;
if (this.options.noServer || this.options.server) {
if (this._server) {
this._removeListeners();
this._removeListeners = this._server = null;
}
if (this.clients) if (!this.clients.size) process.nextTick(emitClose, this);
else this._shouldEmitClose = true;
else process.nextTick(emitClose, this);
} else {
const server = this._server;
this._removeListeners();
this._removeListeners = this._server = null;
server.close(() => {
emitClose(this);
});
}
}
/**
* See if a given request should be handled by this server instance.
*
* @param {http.IncomingMessage} req Request object to inspect
* @return {Boolean} `true` if the request is valid, else `false`
* @public
*/
shouldHandle(req) {
if (this.options.path) {
const index = req.url.indexOf("?");
if ((index !== -1 ? req.url.slice(0, index) : req.url) !== this.options.path) return false;
}
return true;
}
/**
* Handle a HTTP Upgrade request.
*
* @param {http.IncomingMessage} req The request object
* @param {Duplex} socket The network socket between the server and client
* @param {Buffer} head The first packet of the upgraded stream
* @param {Function} cb Callback
* @public
*/
handleUpgrade(req, socket, head, cb) {
socket.on("error", socketOnError);
const key = req.headers["sec-websocket-key"];
const upgrade = req.headers.upgrade;
const version = +req.headers["sec-websocket-version"];
if (req.method !== "GET") {
abortHandshakeOrEmitwsClientError(this, req, socket, 405, "Invalid HTTP method");
return;
}
if (upgrade === void 0 || upgrade.toLowerCase() !== "websocket") {
abortHandshakeOrEmitwsClientError(this, req, socket, 400, "Invalid Upgrade header");
return;
}
if (key === void 0 || !keyRegex.test(key)) {
abortHandshakeOrEmitwsClientError(this, req, socket, 400, "Missing or invalid Sec-WebSocket-Key header");
return;
}
if (version !== 13 && version !== 8) {
abortHandshakeOrEmitwsClientError(this, req, socket, 400, "Missing or invalid Sec-WebSocket-Version header", { "Sec-WebSocket-Version": "13, 8" });
return;
}
if (!this.shouldHandle(req)) {
abortHandshake(socket, 400);
return;
}
const secWebSocketProtocol = req.headers["sec-websocket-protocol"];
let protocols = /* @__PURE__ */ new Set();
if (secWebSocketProtocol !== void 0) try {
protocols = subprotocol.parse(secWebSocketProtocol);
} catch (err) {
abortHandshakeOrEmitwsClientError(this, req, socket, 400, "Invalid Sec-WebSocket-Protocol header");
return;
}
const secWebSocketExtensions = req.headers["sec-websocket-extensions"];
const extensions = {};
if (this.options.perMessageDeflate && secWebSocketExtensions !== void 0) {
const perMessageDeflate = new PerMessageDeflate({
...this.options.perMessageDeflate,
isServer: true,
maxPayload: this.options.maxPayload
});
try {
const offers = extension.parse(secWebSocketExtensions);
if (offers[PerMessageDeflate.extensionName]) {
perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
}
} catch (err) {
abortHandshakeOrEmitwsClientError(this, req, socket, 400, "Invalid or unacceptable Sec-WebSocket-Extensions header");
return;
}
}
if (this.options.verifyClient) {
const info = {
origin: req.headers[`${version === 8 ? "sec-websocket-origin" : "origin"}`],
secure: !!(req.socket.authorized || req.socket.encrypted),
req
};
if (this.options.verifyClient.length === 2) {
this.options.verifyClient(info, (verified, code, message, headers) => {
if (!verified) return abortHandshake(socket, code || 401, message, headers);
this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
});
return;
}
if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
}
this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
}
/**
* Upgrade the connection to WebSocket.
*
* @param {Object} extensions The accepted extensions
* @param {String} key The value of the `Sec-WebSocket-Key` header
* @param {Set} protocols The subprotocols
* @param {http.IncomingMessage} req The request object
* @param {Duplex} socket The network socket between the server and client
* @param {Buffer} head The first packet of the upgraded stream
* @param {Function} cb Callback
* @throws {Error} If called more than once with the same socket
* @private
*/
completeUpgrade(extensions, key, protocols, req, socket, head, cb) {
if (!socket.readable || !socket.writable) return socket.destroy();
if (socket[kWebSocket]) throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");
if (this._state > RUNNING) return abortHandshake(socket, 503);
const headers = [
"HTTP/1.1 101 Switching Protocols",
"Upgrade: websocket",
"Connection: Upgrade",
`Sec-WebSocket-Accept: ${createHash("sha1").update(key + GUID).digest("base64")}`
];
const ws = new this.options.WebSocket(null, void 0, this.options);
if (protocols.size) {
const protocol = this.options.handleProtocols ? this.options.handleProtocols(protocols, req) : protocols.values().next().value;
if (protocol) {
headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
ws._protocol = protocol;
}
}
if (extensions[PerMessageDeflate.extensionName]) {
const params = extensions[PerMessageDeflate.extensionName].params;
const value = extension.format({ [PerMessageDeflate.extensionName]: [params] });
headers.push(`Sec-WebSocket-Extensions: ${value}`);
ws._extensions = extensions;
}
this.emit("headers", headers, req);
socket.write(headers.concat("\r\n").join("\r\n"));
socket.removeListener("error", socketOnError);
ws.setSocket(socket, head, {
allowSynchronousEvents: this.options.allowSynchronousEvents,
maxBufferedChunks: this.options.maxBufferedChunks,
maxFragments: this.options.maxFragments,
maxPayload: this.options.maxPayload,
skipUTF8Validation: this.options.skipUTF8Validation
});
if (this.clients) {
this.clients.add(ws);
ws.on("close", () => {
this.clients.delete(ws);
if (this._shouldEmitClose && !this.clients.size) process.nextTick(emitClose, this);
});
}
cb(ws, req);
}
};
module.exports = WebSocketServer;
/**
* Add event listeners on an `EventEmitter` using a map of <event, listener>
* pairs.
*
* @param {EventEmitter} server The event emitter
* @param {Object.<String, Function>} map The listeners to add
* @return {Function} A function that will remove the added listeners when
* called
* @private
*/
function addListeners(server, map) {
for (const event of Object.keys(map)) server.on(event, map[event]);
return function removeListeners() {
for (const event of Object.keys(map)) server.removeListener(event, map[event]);
};
}
/**
* Emit a `'close'` event on an `EventEmitter`.
*
* @param {EventEmitter} server The event emitter
* @private
*/
function emitClose(server) {
server._state = CLOSED;
server.emit("close");
}
/**
* Handle socket errors.
*
* @private
*/
function socketOnError() {
this.destroy();
}
/**
* Close the connection when preconditions are not fulfilled.
*
* @param {Duplex} socket The socket of the upgrade request
* @param {Number} code The HTTP response status code
* @param {String} [message] The HTTP response body
* @param {Object} [headers] Additional HTTP response headers
* @private
*/
function abortHandshake(socket, code, message, headers) {
message = message || http.STATUS_CODES[code];
headers = {
Connection: "close",
"Content-Type": "text/html",
"Content-Length": Buffer.byteLength(message),
...headers
};
socket.once("finish", socket.destroy);
socket.end(`HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` + Object.keys(headers).map((h) => `${h}: ${headers[h]}`).join("\r\n") + "\r\n\r\n" + message);
}
/**
* Emit a `'wsClientError'` event on a `WebSocketServer` if there is at least
* one listener for it, otherwise call `abortHandshake()`.
*
* @param {WebSocketServer} server The WebSocket server
* @param {http.IncomingMessage} req The request object
* @param {Duplex} socket The socket of the upgrade request
* @param {Number} code The HTTP response status code
* @param {String} message The HTTP response body
* @param {Object} [headers] The HTTP response headers
* @private
*/
function abortHandshakeOrEmitwsClientError(server, req, socket, code, message, headers) {
if (server.listenerCount("wsClientError")) {
const err = new Error(message);
Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);
server.emit("wsClientError", err, socket, req);
} else abortHandshake(socket, code, message, headers);
}
}));
require_stream();
require_extension();
require_permessage_deflate();
require_receiver();
require_sender();
require_subprotocol();
var import_websocket = /* @__PURE__ */ __toESM(require_websocket(), 1);
require_websocket_server();
var wrapper_default = import_websocket.default;
//#endregion
//#region node_modules/.pnpm/node-network-devtools@1.0.30_undici@8.10.0_utf-8-validate@5.0.10/node_modules/node-network-devtools/dist/index.mjs
function se(n) {
const e = {};
return n.forEach((t, r) => {
e[r] = t;
}), e;
}
const W = [
"nodebuffer",
"arraybuffer",
"fragments",
typeof Blob < "u" ? "blob" : null
].filter(Boolean);
const M = Buffer.alloc(0);
const me = Symbol("status-code");
const ge = Symbol("websocket");
const we = Buffer[Symbol.species];
function S(n, e) {
if (n.length === 0) return M;
if (n.length === 1) return n[0];
const t = Buffer.allocUnsafe(e);
let r = 0;
for (let s = 0; s < n.length; s++) {
const i = n[s];
t.set(i, r), r += i.length;
}
return r < e ? new we(t.buffer, t.byteOffset, r) : t;
}
function ye(n, e) {
for (let t = 0; t < n.length; t++) n[t] ^= e[t & 3];
}
function Ee(n) {
return n.length === n.buffer.byteLength ? n.buffer : n.buffer.slice(n.byteOffset, n.byteOffset + n.length);
}
const H = Symbol("kDone");
const N = Symbol("kRun");
var Re = class {
/**
* Creates a new `Limiter`.
*
* @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
* to run concurrently
*/
constructor(e = Infinity) {
this[H] = () => {
this.pending--, this[N]();
}, this.concurrency = e, this.jobs = [], this.pending = 0;
}
/**
* Adds a job to the queue.
*
* @param {Function} job The job to run
* @public
*/
add(e) {
this.jobs.push(e), this[N]();
}
/**
* Removes a job from the queue and runs it if possible.
*
* @private
*/
[N]() {
if (this.pending !== this.concurrency && this.jobs.length) {
const e = this.jobs.shift();
this.pending++, e(this[H]);
}
}
};
const Se = Buffer.from([
0,
0,
255,
255
]);
const O = Symbol("permessage-deflate");
const w = Symbol("total-length");
const v = Symbol("callback");
const y = Symbol("buffers");
const ve = Symbol("error");
let L;
var V = class {
constructor(e = {}, t = !1, r = 0) {
if (this._maxPayload = r | 0, this._options = e, this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024, this._isServer = !!t, this._deflate = null, this._inflate = null, this.params = null, !L) L = new Re(this._options.concurrencyLimit !== void 0 ? this._options.concurrencyLimit : 10);
}
static get extensionName() {
return "permessage-deflate";
}
offer() {
const e = {};
return this._options.serverNoContextTakeover && (e.server_no_context_takeover = !0), this._options.clientNoContextTakeover && (e.client_no_context_takeover = !0), this._options.serverMaxWindowBits && (e.server_max_window_bits = this._options.serverMaxWindowBits), this._options.clientMaxWindowBits ? e.client_max_window_bits = this._options.clientMaxWindowBits : this._options.clientMaxWindowBits ?? (e.client_max_window_bits = !0), e;
}
accept(e) {
return e = this.normalizeParams(e), this.params = this._isServer ? this.acceptAsServer(e) : this.acceptAsClient(e), this.params;
}
cleanup() {
if (this._inflate && (this._inflate.close(), this._inflate = null), this._deflate) {
const e = this._deflate[v];
this._deflate.close(), this._deflate = null, e && e(/* @__PURE__ */ new Error("The deflate stream was closed while data was being processed"));
}
}
acceptAsServer(e) {
const t = this._options, r = e.find((s) => !(t.serverNoContextTakeover === !1 && s.server_no_context_takeover || s.server_max_window_bits && (t.serverMaxWindowBits === !1 || typeof t.serverMaxWindowBits == "number" && t.serverMaxWindowBits > s.server_max_window_bits) || typeof t.clientMaxWindowBits == "number" && !s.client_max_window_bits));
if (!r) throw new Error("None of the extension offers can be accepted");
return t.serverNoContextTakeover && (r.server_no_context_takeover = !0), t.clientNoContextTakeover && (r.client_no_context_takeover = !0), typeof t.serverMaxWindowBits == "number" && (r.server_max_window_bits = t.serverMaxWindowBits), typeof t.clientMaxWindowBits == "number" ? r.client_max_window_bits = t.clientMaxWindowBits : (r.client_max_window_bits === !0 || t.clientMaxWindowBits === !1) && delete r.client_max_window_bits, r;
}
acceptAsClient(e) {
const t = e[0];
if (this._options.clientNoContextTakeover === !1 && t.client_no_context_takeover) throw new Error("Unexpected parameter \"client_no_context_takeover\"");
if (!t.client_max_window_bits) typeof this._options.clientMaxWindowBits == "number" && (t.client_max_window_bits = this._options.clientMaxWindowBits);
else if (this._options.clientMaxWindowBits === !1 || typeof this._options.clientMaxWindowBits == "number" && t.client_max_window_bits > this._options.clientMaxWindowBits) throw new Error("Unexpected or invalid parameter \"client_max_window_bits\"");
return t;
}
normalizeParams(e) {
return e.forEach((t) => {
Object.keys(t).forEach((r) => {
let s = t[r];
if (s.length > 1) throw new Error(`Parameter "${r}" must have only a single value`);
if (s = s[0], r === "client_max_window_bits") {
if (s !== !0) {
const i = +s;
if (!Number.isInteger(i) || i < 8 || i > 15) throw new TypeError(`Invalid value for parameter "${r}": ${s}`);
s = i;
} else if (!this._isServer) throw new TypeError(`Invalid value for parameter "${r}": ${s}`);
} else if (r === "server_max_window_bits") {
const i = +s;
if (!Number.isInteger(i) || i < 8 || i > 15) throw new TypeError(`Invalid value for parameter "${r}": ${s}`);
s = i;
} else if (r === "client_no_context_takeover" || r === "server_no_context_takeover") {
if (s !== !0) throw new TypeError(`Invalid value for parameter "${r}": ${s}`);
} else throw new Error(`Unknown parameter "${r}"`);
t[r] = s;
});
}), e;
}
decompress(e, t, r) {
L?.add((s) => {
this._decompress(e, t, (i, o) => {
s(), r(i, o);
});
});
}
compress(e, t, r) {
L?.add((s) => {
this._compress(e, t, (i, o) => {
s(), r(i, o);
});
});
}
_decompress(e, t, r) {
const s = this._isServer ? "client" : "server";
if (!this._inflate) {
const i = `${s}_max_window_bits`, o = typeof this.params[i] != "number" ? R.constants.Z_DEFAULT_WINDOWBITS : this.params[i];
this._inflate = R.createInflateRaw({
...this._options.zlibInflateOptions,
windowBits: o
}), this._inflate[O] = this, this._inflate[w] = 0, this._inflate[y] = [], this._inflate.on("error", be), this._inflate.on("data", xe);
}
this._inflate[v] = r, this._inflate.write(e), t && this._inflate.write(Se), this._inflate.flush(() => {
const i = this._inflate[ve];
if (i) {
this._inflate.close(), this._inflate = null, r(i);
return;
}
const o = S(this._inflate[y], this._inflate[w]);
if (this._maxPayload < 1 || o.length <= this._maxPayload) {
r(null, o);
return;
}
r(/* @__PURE__ */ new RangeError("Max payload size exceeded"), null);
});
}
_compress(e, t, r) {
const s = this._isServer ? "server" : "client";
if (!this._deflate) {
const i = `${s}_max_window_bits`, o = typeof this.params[i] != "number" ? R.constants.Z_DEFAULT_WINDOWBITS : this.params[i];
this._deflate = R.createDeflateRaw({
...this._options.zlibDeflateOptions,
windowBits: o
}), this._deflate[w] = 0, this._deflate[y] = [], this._deflate.on("error", Le), this._deflate.on("data", Te);
}
this._deflate[v] = r, this._deflate.write(e), t && this._deflate.flush(R.Z_SYNC_FLUSH, () => {
const i = S(this._deflate[y], this._deflate[w]);
if (this._maxPayload < 1 || i.length <= this._maxPayload) {
r(null, i);
return;
}
r(/* @__PURE__ */ new RangeError("Max payload size exceeded"), null);
});
}
};
function be(n) {
this[O][v](n);
}
function xe(n) {
this[w] += n.length, this[y].push(n);
}
function Le(n) {
this[O][v](n);
}
function Te(n) {
this[w] += n.length, this[y].push(n);
}
function ke(n) {
return n >= 1e3 && n <= 1014 && n !== 1004 && n !== 1005 && n !== 1006 || n >= 3e3 && n <= 4999;
}
function $(n) {
const e = n.length;
let t = 0;
for (; t < e;) if (!(n[t] & 128)) t++;
else if ((n[t] & 224) === 192) {
if (t + 1 === e || (n[t + 1] & 192) !== 128 || (n[t] & 254) === 192) return !1;
t += 2;
} else if ((n[t] & 240) === 224) {
if (t + 2 >= e || (n[t + 1] & 192) !== 128 || (n[t + 2] & 192) !== 128 || n[t] === 224 && (n[t + 1] & 224) === 128 || n[t] === 237 && (n[t + 1] & 224) === 160) return !1;
t += 3;
} else if ((n[t] & 248) === 240) {
if (t + 3 >= e || (n[t + 1] & 192) !== 128 || (n[t + 2] & 192) !== 128 || (n[t + 3] & 192) !== 128 || n[t] === 240 && (n[t + 1] & 240) === 128 || n[t] === 244 && n[t + 1] > 143 || n[t] > 244) return !1;
t += 4;
} else return !1;
return !0;
}
const G = isUtf8 ? function(n) {
return n.length < 24 ? $(n) : isUtf8(n);
} : $;
var z;
const T = Buffer[Symbol.species];
const m = 0;
const j = 1;
const Y = 2;
const X = 3;
const B = 4;
const A = 5;
const k = 6;
var J = class extends (z = Writable, z) {
constructor(e = {}) {
super(), this._allowSynchronousEvents = e.allowSynchronousEvents !== void 0 ? e.allowSynchronousEvents : !0, this._binaryType = e.binaryType || W[0], this._extensions = e.extensions || {}, this._isServer = !!e.isServer, this._maxPayload = e.maxPayload || 0, this._skipUTF8Validation = !!e.skipUTF8Validation, this[ge] = void 0, this._bufferedBytes = 0, this._buffers = [], this._compressed = !1, this._payloadLength = 0, this._mask = void 0, this._fragmented = 0, this._masked = !1, this._fin = !1, this._opcode = 0, this._totalPayloadLength = 0, this._messageLength = 0, this._fragments = [], this._errored = !1, this._loop = !1, this._state = m;
}
/**
* Implements `Writable.prototype._write()`.
*
* @param {Buffer} chunk The chunk of data to write
* @param {string} encoding The character encoding of `chunk`
* @param {Function} cb Callback
* @private
*/
_write(e, t, r) {
if (this._opcode === 8 && this._state === m) return r();
this._bufferedBytes += e.length, this._buffers.push(e), this.startLoop(r);
}
/**
* Consumes `n` bytes from the buffered data.
*
* @param {number} n The number of bytes to consume
* @return {Buffer} The consumed bytes
* @private
*/
consume(e) {
if (this._bufferedBytes -= e, e === this._buffers[0].length) return this._buffers.shift();
if (e < this._buffers[0].length) {
const r = this._buffers[0];
return this._buffers[0] = new T(r.buffer, r.byteOffset + e, r.length - e), new T(r.buffer, r.byteOffset, e);
}
const t = Buffer.allocUnsafe(e);
do {
const r = this._buffers[0], s = t.length - e;
e >= r.length ? t.set(this._buffers.shift(), s) : (t.set(new Uint8Array(r.buffer, r.byteOffset, e), s), this._buffers[0] = new T(r.buffer, r.byteOffset + e, r.length - e)), e -= r.length;
} while (e > 0);
return t;
}
/**
* Starts the parsing loop.
*
* @param {Function} cb Callback
* @private
*/
startLoop(e) {
this._loop = !0;
do
switch (this._state) {
case m:
this.getInfo(e);
break;
case j:
this.getPayloadLength16(e);
break;
case Y:
this.getPayloadLength64(e);
break;
case X:
this.getMask();
break;
case B:
this.getData(e);
break;
case A:
case k:
this._loop = !1;
return;
}
while (this._loop);
this._errored || e();
}
/**
* Reads the first two bytes of a frame.
*
* @param {Function} cb Callback
* @private
*/
getInfo(e) {
if (this._bufferedBytes < 2) {
this._loop = !1;
return;
}
const t = this.consume(2);
if (t[0] & 48) {
e(this.createError(RangeError, "RSV2 and RSV3 must be clear", !0, 1002, "WS_ERR_UNEXPECTED_RSV_2_3"));
return;
}
const r = (t[0] & 64) === 64;
if (r && !this._extensions[V.extensionName]) {
e(this.createError(RangeError, "RSV1 must be clear", !0, 1002, "WS_ERR_UNEXPECTED_RSV_1"));
return;
}
if (this._fin = (t[0] & 128) === 128, this._opcode = t[0] & 15, this._payloadLength = t[1] & 127, this._opcode === 0) {
if (r) {
e(this.createError(RangeError, "RSV1 must be clear", !0, 1002, "WS_ERR_UNEXPECTED_RSV_1"));
return;
}
if (!this._fragmented) {
e(this.createError(RangeError, "invalid opcode 0", !0, 1002, "WS_ERR_INVALID_OPCODE"));
return;
}
this._opcode = this._fragmented;
} else if (this._opcode === 1 || this._opcode === 2) {
if (this._fragmented) {
e(this.createError(RangeError, `invalid opcode ${this._opcode}`, !0, 1002, "WS_ERR_INVALID_OPCODE"));
return;
}
this._compressed = r;
} else if (this._opcode > 7 && this._opcode < 11) {
if (!this._fin) {
e(this.createError(RangeError, "FIN must be set", !0, 1002, "WS_ERR_EXPECTED_FIN"));
return;
}
if (r) {
e(this.createError(RangeError, "RSV1 must be clear", !0, 1002, "WS_ERR_UNEXPECTED_RSV_1"));
return;
}
if (this._payloadLength > 125 || this._opcode === 8 && this._payloadLength === 1) {
e(this.createError(RangeError, `invalid payload length ${this._payloadLength}`, !0, 1002, "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH"));
return;
}
} else {
e(this.createError(RangeError, `invalid opcode ${this._opcode}`, !0, 1002, "WS_ERR_INVALID_OPCODE"));
return;
}
if (!this._fin && !this._fragmented && (this._fragmented = this._opcode), this._masked = (t[1] & 128) === 128, this._isServer) {
if (!this._masked) {
e(this.createError(RangeError, "MASK must be set", !0, 1002, "WS_ERR_EXPECTED_MASK"));
return;
}
} else if (this._masked) {
e(this.createError(RangeError, "MASK must be clear", !0, 1002, "WS_ERR_UNEXPECTED_MASK"));
return;
}
this._payloadLength === 126 ? this._state = j : this._payloadLength === 127 ? this._state = Y : this.haveLength(e);
}
/**
* Reads the next two bytes and stores the message length.
*
* @param {Function} cb Callback
* @private
*/
getPayloadLength16(e) {
if (this._bufferedBytes < 2) {
this._loop = !1;
return;
}
this._payloadLength = this.consume(2).readUInt16BE(0), this.haveLength(e);
}
/**
* Reads the next eight bytes and stores the message length.
*
* @param {Function} cb Callback
* @private
*/
getPayloadLength64(e) {
if (this._bufferedBytes < 8) {
this._loop = !1;
return;
}
const t = this.consume(8), r = t.readUInt32BE(0);
if (r > Math.pow(2, 21) - 1) {
e(this.createError(RangeError, "Unsupported WebSocket frame: payload length > 2^53 - 1", !1, 1009, "WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH"));
return;
}
this._payloadLength = r * Math.pow(2, 32) + t.readUInt32BE(4), this.haveLength(e);
}
/**
* Payload length has been read.
*
* @param {Function} cb Callback
* @private
*/
haveLength(e) {
if (this._payloadLength && this._opcode < 8 && (this._totalPayloadLength += this._payloadLength, this._totalPayloadLength > this._maxPayload && this._maxPayload > 0)) {
e(this.createError(RangeError, "Max payload size exceeded", !1, 1009, "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"));
return;
}
this._masked ? this._state = X : this._state = B;
}
/**
* Reads the mask bytes.
*
* @private
*/
getMask() {
if (this._bufferedBytes < 4) {
this._loop = !1;
return;
}
this._mask = this.consume(4), this._state = B;
}
/**
* Reads data bytes.
*
* @param {Function} cb Callback
* @private
*/
getData(e) {
let t = M;
if (this._payloadLength) {
if (this._bufferedBytes < this._payloadLength) {
this._loop = !1;
return;
}
t = this.consume(this._payloadLength), this._masked && this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3] && ye(t, this._mask);
}
if (this._opcode > 7) {
this.controlMessage(t, e);
return;
}
if (this._compressed) {
this._state = A, this.decompress(t, e);
return;
}
t.length && (this._messageLength = this._totalPayloadLength, this._fragments.push(t)), this.dataMessage(e);
}
/**
* Decompresses data.
*
* @param {Buffer} data Compressed data
* @param {Function} cb Callback
* @private
*/
decompress(e, t) {
this._extensions[V.extensionName].decompress(e, this._fin, (s, i) => {
if (s) return t(s);
if (i && i.length) {
if (this._messageLength += i.length, this._messageLength > this._maxPayload && this._maxPayload > 0) {
t(this.createError(RangeError, "Max payload size exceeded", !1, 1009, "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"));
return;
}
this._fragments.push(i);
}
this.dataMessage(t), this._state === m && this.startLoop(t);
});
}
/**
* Handles a data message.
*
* @param {Function} cb Callback
* @private
*/
dataMessage(e) {
if (!this._fin) {
this._state = m;
return;
}
const t = this._messageLength, r = this._fragments;
if (this._totalPayloadLength = 0, this._messageLength = 0, this._fragmented = 0, this._fragments = [], this._opcode === 2) {
let s;
this._binaryType === "nodebuffer" ? s = S(r, t) : this._binaryType === "arraybuffer" ? s = Ee(S(r, t)) : this._binaryType === "blob" ? s = new Blob(r) : s = r, this._allowSynchronousEvents ? (this.emit("message", s, !0), this._state = m) : (this._state = k, setImmediate(() => {
this.emit("message", s, !0), this._state = m, this.startLoop(e);
}));
} else {
const s = S(r, t);
if (!this._skipUTF8Validation && !G(s)) {
e(this.createError(Error, "invalid UTF-8 sequence", !0, 1007, "WS_ERR_INVALID_UTF8"));
return;
}
this._state === A || this._allowSynchronousEvents ? (this.emit("message", s, !1), this._state = m) : (this._state = k, setImmediate(() => {
this.emit("message", s, !1), this._state = m, this.startLoop(e);
}));
}
}
/**
* Handles a control message.
*
* @param {Buffer} data Data to handle
* @return {(Error|RangeError|undefined)} A possible error
* @private
*/
controlMessage(e, t) {
if (this._opcode === 8) {
if (e.length === 0) this._loop = !1, this.emit("conclude", 1005, M), this.end();
else {
const r = e.readUInt16BE(0);
if (!ke(r)) {
t(this.createError(RangeError, `invalid status code ${r}`, !0, 1002, "WS_ERR_INVALID_CLOSE_CODE"));
return;
}
const s = new T(e.buffer, e.byteOffset + 2, e.length - 2);
if (!this._skipUTF8Validation && !G(s)) {
t(this.createError(Error, "invalid UTF-8 sequence", !0, 1007, "WS_ERR_INVALID_UTF8"));
return;
}
this._loop = !1, this.emit("conclude", r, s), this.end();
}
this._state = m;
return;
}
this._allowSynchronousEvents ? (this.emit(this._opcode === 9 ? "ping" : "pong", e), this._state = m) : (this._state = k, setImmediate(() => {
this.emit(this._opcode === 9 ? "ping" : "pong", e), this._state = m, this.startLoop(t);
}));
}
createError(e, t, r, s, i) {
this._loop = !1, this._errored = !0;
const o = new e(r ? `Invalid WebSocket frame: ${t}` : t);
return Error.captureStackTrace(o, this.createError), o.code = i, o[me] = s, o;
}
};
function K(n, e, t) {
const r = n.write;
return n.write = (s) => {
let i;
return Buffer.isBuffer(s) ? i = s.toString("utf-8") : typeof s == "string" ? i = s : s != null ? i = JSON.stringify(s) : i = "", e.requestData ? e.requestData += i : e.requestData = i, r.bind(n)(s);
}, n.on("error", () => {
e.responseStatusCode = 0, e.requestEndTime = (/* @__PURE__ */ new Date()).getTime(), t.sendRequest("endRequest", e);
}), e.isWebSocket() ? n.on("upgrade", async (s, i, o) => {
const c = i.write;
if (e.isHiden()) return;
await t.send({
type: "Network.webSocketCreated",
data: {
requestId: e.id,
url: e.url,
initiator: e.initiator,
response: s
}
});
const h = new J({
allowSynchronousEvents: !0,
binaryType: W[0],
isServer: !1
}), _ = new J({
allowSynchronousEvents: !0,
binaryType: W[0],
isServer: !0
}), a = (d) => {
const p = d.toString();
t.send({
type: "Network.webSocketFrameReceived",
data: {
requestId: e.id,
response: {
payloadData: p,
opcode: 1,
mask: !1
}
}
});
}, u = (d) => {
const p = d.toString();
t.send({
type: "Network.webSocketFrameSent",
data: {
requestId: e.id,
response: {
payloadData: p,
opcode: 1,
mask: !0
}
}
});
};
h.on("message", a), _.on("message", u);
let f;
i.write = (d, ...p) => {
const l = Buffer.from(d);
return _.write(l), c.call(i, d, ...p);
}, i.addListener("data", (d) => {
const p = Buffer.from(d);
h.write(p);
}), i.addListener("close", () => {
f = i.read(), f !== null && (h.write(f), _.write(f)), h.end(), _.end(), h.removeAllListeners(), _.removeAllListeners(), t.send({
method: "Network.webSocketClosed",
params: {
requestId: e.id,
timestamp: w$1()
}
});
}), i.addListener("end", () => {
h.end(), _.end(), h.removeAllListeners(), _.removeAllListeners();
});
}) : t.sendRequest("registerRequest", e), n;
}
function Ie(n, e, t) {
return (r) => {
e.responseHeaders = r.headers, typeof n == "function" && n(r), t.responseRequest(e.id, r);
};
}
function Z(n, e) {
let t = n.setHeader;
n.setHeader = function(r, s) {
return Array.isArray(s) ? s.forEach((i) => {
e.requestHeaders[r] = i;
}) : e.requestHeaders[r] = s, t.call(n, r, s);
};
}
function Ne(n, e, t) {
return (s, i, o) => {
let c, h, _;
typeof s == "string" || s instanceof URL ? (c = s, h = i, _ = o) : (h = s, _ = i);
const a = new j$1();
if (typeof c == "string") a.url = c, a.method = "GET";
else if (c instanceof URL) a.url = c.toString(), a.method = "GET";
else if (h && typeof h != "string" && !(h instanceof URL)) a.url = `${e ? "https" : "http"}://${h.hostname || h.host}${h.path}`;
h && typeof h != "string" && !(h instanceof URL) && (a.method = h.method, a.requestHeaders = h.headers), a.loadCallFrames(), a.isWebSocket() && (a.url = a.url.replace("http://", "ws://").replace("https://", "wss://")), t.sendRequest("initRequest", a);
const u = Ie(_, a, t);
if (typeof s == "string" || s instanceof URL) {
const f = n(c, h, u);
return Z(f, a), K(f, a, t);
} else {
const f = n(h, u);
return Z(f, a), K(f, a, t);
}
};
}
const Be = (n) => new Promise((e) => setTimeout(e, n));
const Ae = (n, e) => {
try {
return Number(n) === process.pid ? Promise.resolve(!0) : (process.kill(Number(n), 0), new Promise((t) => {
const r = ue.createServer();
r.once("error", (s) => {
s.code === "EADDRINUSE" && t(!1), t(!1);
}), r.once("listening", () => {
r.close(() => t(!0));
}), r.listen(e);
}));
} catch {
return Promise.resolve(!1);
}
};
const P = (n) => {
try {
I.unlinkSync(n);
} catch {}
};
let re = null;
function b() {
return re;
}
function Q(n) {
re = n;
}
var ee = class extends Error {
constructor(e) {
super(e);
}
};
var Pe = class {
constructor(e) {
this.options = e, this.ws = new Promise(async (t, r) => {
const s = resolve(H$1, `./${e.key}`);
if (I.existsSync(s)) {
const o = I.readFileSync(s, "utf-8");
if (await Be(1), await Ae(o, e.port)) {
_("The main process with same options is already running, skip it.");
return;
}
P(s);
}
I.writeFileSync(s, `${process.pid}`);
const i = new wrapper_default(`ws://127.0.0.1:${e.port}`);
i.on("open", () => {
P(s), t(i);
}), i.on("error", () => {
this.openProcess(() => {
P(s);
const o = new wrapper_default(`ws://127.0.0.1:${e.port}`);
o.on("open", () => {
t(o);
}), o.on("error", r);
});
});
}), this.ws.then((t) => {
this.healthCheck(), t.on("error", (r) => {
console.error("MainProcess Socket Error: ", r);
});
}).catch((t) => {
if (!(t instanceof ee)) throw t;
});
}
openProcess(e) {
(() => {
const r = fork(resolve(H$1, "./fork"), { env: {
...process.env,
NETWORK_OPTIONS: JSON.stringify(this.options)
} }), s = (i) => {
i === "ready" && (e && e(r), r.off("message", s));
};
r.on("message", s), this.cp = r;
})();
}
async send(e) {
if (b()?.isAborted) return;
const r = await this.ws.catch((s) => {
if (s instanceof ee) return null;
throw s;
});
r && r.send(JSON.stringify(e));
}
sendRequest(e, t) {
const r = b();
let s = t;
return r && (r.request = s, r.pipes.filter((o) => o.type === e).map((o) => o.pipe).forEach((o) => {
s = o(s);
}), r.request = s), this.send({
type: e,
data: t
}), this;
}
async healthCheck() {
const e = await this.ws, t = () => {
e.send(JSON.stringify({
type: "healthcheck",
data: {}
}));
};
t(), setInterval(t, 2e3);
}
responseRequest(e, t) {
const r = [];
t.on("data", (s) => {
r.push(s);
}), t.on("end", () => {
const s = Buffer.concat(r);
this.ws.then((i) => {
i.send(JSON.stringify({
type: "responseData",
data: {
id: e,
rawData: s,
statusCode: t.statusCode,
headers: t.headers
}
}), { binary: !0 });
});
});
}
async dispose() {
const e = await this.ws;
e.removeAllListeners(), e.terminate(), this.cp && (this.cp.removeAllListeners(), this.cp.kill(), this.cp = void 0);
}
};
function We(n) {
if (!globalThis.fetch) return;
const e = globalThis.fetch;
return globalThis.fetch = ne(e, n), () => {
globalThis.fetch = e;
};
}
function ne(n, e) {
return function(t, r) {
const s = new j$1();
s.requestStartTime = Date.now(), Q({
request: s,
pipes: [],
isAborted: !1
}), typeof t == "string" ? s.url = t : t instanceof URL && (s.url = t.toString()), s.method = r?.method ?? "GET";
const i = r?.headers;
if (i instanceof Headers) s.requestHeaders = se(i);
else s.requestHeaders = i ?? {};
s.requestData = r?.body;
const o = n(t, r).then(Ue(s, e)).catch(Ce(s, e)).finally(() => {
Q(null);
});
return e.sendRequest("initRequest", s).sendRequest("registerRequest", s), o;
};
}
function Me(n) {
return (n.headers.get("content-type") || "").includes("text/event-stream");
}
async function Oe(n, e, t) {
const r = n.clone().body;
if (!r) return;
const s = r.getReader(), i = new TextDecoder();
let o = "";
const c = [];
t.sendRequest("updateRequest", e);
try {
for (;;) {
const { done: u, value: f } = await s.read();
if (u) break;
if (f) {
c.push(f), o += i.decode(f, { stream: !0 });
const d = o.split(`
`);
o = d.pop() || "";
let p = "message", l = "", E = "";
for (const g of d) g.startsWith("event:") ? p = g.slice(6).trim() : g.startsWith("data:") ? l += (l ? `
` : "") + g.slice(5).trim() : g.startsWith("id:") ? E = g.slice(3).trim() : g === "" && (l && t.send({
type: "eventSourceMessage",
data: {
requestId: e.id,
eventName: p,
eventId: E,
data: l
}
}), p = "message", l = "", E = "");
}
}
if (o.trim()) {
const u = o.split(`
`);
let f = "message", d = "", p = "";
for (const l of u) l.startsWith("event:") ? f = l.slice(6).trim() : l.startsWith("data:") ? d += (d ? `
` : "") + l.slice(5).trim() : l.startsWith("id:") && (p = l.slice(3).trim());
d && t.send({
type: "eventSourceMessage",
data: {
requestId: e.id,
eventName: f,
eventId: p,
data: d
}
});
}
const h = c.reduce((u, f) => u + f.length, 0), _ = new Uint8Array(h);
let a = 0;
for (const u of c) _.set(u, a), a += u.length;
e.responseData = Buffer.from(_), e.responseInfo.dataLength = h, e.responseInfo.encodedDataLength = h;
} catch {
if (c.length > 0) {
const _ = c.reduce((f, d) => f + d.length, 0), a = new Uint8Array(_);
let u = 0;
for (const f of c) a.set(f, u), u += f.length;
e.responseData = Buffer.from(a), e.responseInfo.dataLength = _, e.responseInfo.encodedDataLength = _;
}
} finally {
e.requestEndTime = Date.now(), t.sendRequest("updateRequest", e).sendRequest("endRequest", e);
}
}
function Ue(n, e) {
return (t) => (n.requestEndTime = (/* @__PURE__ */ new Date()).getTime(), n.responseHeaders = se(t.headers), n.responseStatusCode = t.status || 0, Me(t) ? (Oe(t, n, e), t) : (t.clone().arrayBuffer().then((r) => {
const s = Buffer.from(r);
n.responseData = s, n.responseInfo.dataLength = s.length, n.responseInfo.encodedDataLength = s.length;
}).finally(() => {
e.sendRequest("updateRequest", n).sendRequest("endRequest", n);
}), t));
}
function Ce(n, e) {
return (t) => {
throw n.requestEndTime = Date.now(), n.responseStatusCode = 0, e.sendRequest("updateRequest", n).sendRequest("endRequest", n), t;
};
}
const Fe = (n) => {
if (!x.fetch) return;
const e = x.fetch;
return x.fetch = ne(e, n), () => {
x.fetch = e;
};
};
const Ze = (n) => {
const e = b();
if (!e) throw new Error("useRegisterRequest must be used in request handler");
e.pipes.push({
pipe: n,
type: "registerRequest"
});
};
function tt(n) {
const { port: e = D, serverPort: t = I$1, autoOpenDevtool: r = !0, intercept: s = {} } = n || {}, { fetch: i = !0, normal: o = !0, undici: c = !1 } = s, h = c && c.fetch, a = new Pe({
port: e,
serverPort: t,
autoOpenDevtool: r,
key: v$1(JSON.stringify({
port: e,
serverPort: t,
autoOpenDevtool: r
}))
}), u = i ? We(a) : void 0, f = /* @__PURE__ */ new WeakMap(), d = [ie, U];
o && d.forEach((l) => {
f.set(l, l.request);
const E = l.request;
l.request = Ne(E, l === U, a);
});
const p = h ? Fe(a) : void 0;
return () => {
u && u(), o && d.forEach((l) => {
l.request = f.get(l), f.delete(l);
}), p && p(), a.dispose();
};
}
//#endregion
//#region lib/utils/ofetch.ts
config.enableRemoteDebugging && process.env.NODE_ENV === "dev" && tt();
const rofetch = createFetch({ fetch: (input, init) => fetch(input, init) }).create({
retryStatusCodes: [
400,
408,
409,
425,
429,
500,
502,
503,
504
],
retry: config.requestRetry,
retryDelay: 1e3,
onResponseError({ request, response, options }) {
if (!options.retry) return;
logger.warn(`Request ${request} with error ${response.status} remaining retry attempts: ${options.retry}`);
if (!(options.headers instanceof Headers)) options.headers = new Headers(options.headers || {});
options.headers.set("x-prefer-proxy", "1");
},
onRequestError({ request, error }) {
logger.error(`Request ${request} fail: ${error.cause} ${error}`);
for (let cause = error.cause; cause instanceof Error; cause = cause.cause) if (cause.message) error.message += ` (${cause.message})`;
},
onResponse({ request, response }) {
if (response.redirected) logger.http(`Redirecting to ${response.url} for ${request}`);
}
});
//#endregion
export { Ze as n, rofetch as t };