@holochain/hc-spin
Version:
CLI to run Holochain apps during development.
1,615 lines (1,614 loc) • 1.4 MB
JavaScript
"use strict";
const msgpack = require("@msgpack/msgpack");
const require$$0$3 = require("events");
const require$$1$1 = require("https");
const require$$2$1 = require("http");
const require$$3 = require("net");
const require$$4 = require("tls");
const require$$1 = require("crypto");
const require$$0$2 = require("stream");
const require$$7 = require("url");
const require$$0 = require("zlib");
const require$$0$1 = require("buffer");
const fs = require("fs");
const path = require("path");
const require$$2 = require("os");
const jsSha512 = require("js-sha512");
const childProcess = require("child_process");
const commander = require("commander");
const electron = require("electron");
const contextMenu = require("electron-context-menu");
const net$1 = require("node:net");
const os = require("node:os");
const node_crypto = require("node:crypto");
const split = require("split");
const utils = require("@electron-toolkit/utils");
function _interopNamespaceDefault(e) {
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
if (e) {
for (const k in e) {
if (k !== "default") {
const d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: () => e[k]
});
}
}
}
n.default = e;
return Object.freeze(n);
}
const childProcess__namespace = /* @__PURE__ */ _interopNamespaceDefault(childProcess);
var CellType;
(function(CellType2) {
CellType2["Provisioned"] = "provisioned";
CellType2["Cloned"] = "cloned";
CellType2["Stem"] = "stem";
})(CellType || (CellType = {}));
var CellProvisioningStrategy;
(function(CellProvisioningStrategy2) {
CellProvisioningStrategy2["Create"] = "create";
CellProvisioningStrategy2["UseExisting"] = "use_existing";
CellProvisioningStrategy2["CreateIfNoExists"] = "create_if_no_exists";
})(CellProvisioningStrategy || (CellProvisioningStrategy = {}));
var AppStatusFilter;
(function(AppStatusFilter2) {
AppStatusFilter2["Enabled"] = "enabled";
AppStatusFilter2["Disabled"] = "disabled";
})(AppStatusFilter || (AppStatusFilter = {}));
const __HC_LAUNCHER_ENV__ = "__HC_LAUNCHER_ENV__";
const __HC_ZOME_CALL_SIGNER__ = "__HC_ZOME_CALL_SIGNER__";
const isLauncher = () => globalThis.window && __HC_LAUNCHER_ENV__ in globalThis.window;
const getLauncherEnvironment = () => isLauncher() ? globalThis.window[__HC_LAUNCHER_ENV__] : void 0;
const getHostZomeCallSigner = () => globalThis.window && globalThis.window[__HC_ZOME_CALL_SIGNER__];
const anyMap = /* @__PURE__ */ new WeakMap();
const eventsMap = /* @__PURE__ */ new WeakMap();
const producersMap = /* @__PURE__ */ new WeakMap();
const anyProducer = Symbol("anyProducer");
const resolvedPromise = Promise.resolve();
const listenerAdded = Symbol("listenerAdded");
const listenerRemoved = Symbol("listenerRemoved");
let canEmitMetaEvents = false;
let isGlobalDebugEnabled = false;
const isEventKeyType = (key) => typeof key === "string" || typeof key === "symbol" || typeof key === "number";
function assertEventName(eventName) {
if (!isEventKeyType(eventName)) {
throw new TypeError("`eventName` must be a string, symbol, or number");
}
}
function assertListener(listener) {
if (typeof listener !== "function") {
throw new TypeError("listener must be a function");
}
}
function getListeners(instance, eventName) {
const events = eventsMap.get(instance);
if (!events.has(eventName)) {
return;
}
return events.get(eventName);
}
function getEventProducers(instance, eventName) {
const key = isEventKeyType(eventName) ? eventName : anyProducer;
const producers = producersMap.get(instance);
if (!producers.has(key)) {
return;
}
return producers.get(key);
}
function enqueueProducers(instance, eventName, eventData) {
const producers = producersMap.get(instance);
if (producers.has(eventName)) {
for (const producer of producers.get(eventName)) {
producer.enqueue(eventData);
}
}
if (producers.has(anyProducer)) {
const item = Promise.all([eventName, eventData]);
for (const producer of producers.get(anyProducer)) {
producer.enqueue(item);
}
}
}
function iterator(instance, eventNames) {
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
let isFinished = false;
let flush = () => {
};
let queue = [];
const producer = {
enqueue(item) {
queue.push(item);
flush();
},
finish() {
isFinished = true;
flush();
}
};
for (const eventName of eventNames) {
let set = getEventProducers(instance, eventName);
if (!set) {
set = /* @__PURE__ */ new Set();
const producers = producersMap.get(instance);
producers.set(eventName, set);
}
set.add(producer);
}
return {
async next() {
if (!queue) {
return { done: true };
}
if (queue.length === 0) {
if (isFinished) {
queue = void 0;
return this.next();
}
await new Promise((resolve) => {
flush = resolve;
});
return this.next();
}
return {
done: false,
value: await queue.shift()
};
},
async return(value) {
queue = void 0;
for (const eventName of eventNames) {
const set = getEventProducers(instance, eventName);
if (set) {
set.delete(producer);
if (set.size === 0) {
const producers = producersMap.get(instance);
producers.delete(eventName);
}
}
}
flush();
return arguments.length > 0 ? { done: true, value: await value } : { done: true };
},
[Symbol.asyncIterator]() {
return this;
}
};
}
function defaultMethodNamesOrAssert(methodNames) {
if (methodNames === void 0) {
return allEmitteryMethods;
}
if (!Array.isArray(methodNames)) {
throw new TypeError("`methodNames` must be an array of strings");
}
for (const methodName of methodNames) {
if (!allEmitteryMethods.includes(methodName)) {
if (typeof methodName !== "string") {
throw new TypeError("`methodNames` element must be a string");
}
throw new Error(`${methodName} is not Emittery method`);
}
}
return methodNames;
}
const isMetaEvent = (eventName) => eventName === listenerAdded || eventName === listenerRemoved;
function emitMetaEvent(emitter, eventName, eventData) {
if (!isMetaEvent(eventName)) {
return;
}
try {
canEmitMetaEvents = true;
emitter.emit(eventName, eventData);
} finally {
canEmitMetaEvents = false;
}
}
class Emittery {
static mixin(emitteryPropertyName, methodNames) {
methodNames = defaultMethodNamesOrAssert(methodNames);
return (target) => {
if (typeof target !== "function") {
throw new TypeError("`target` must be function");
}
for (const methodName of methodNames) {
if (target.prototype[methodName] !== void 0) {
throw new Error(`The property \`${methodName}\` already exists on \`target\``);
}
}
function getEmitteryProperty() {
Object.defineProperty(this, emitteryPropertyName, {
enumerable: false,
value: new Emittery()
});
return this[emitteryPropertyName];
}
Object.defineProperty(target.prototype, emitteryPropertyName, {
enumerable: false,
get: getEmitteryProperty
});
const emitteryMethodCaller = (methodName) => function(...args) {
return this[emitteryPropertyName][methodName](...args);
};
for (const methodName of methodNames) {
Object.defineProperty(target.prototype, methodName, {
enumerable: false,
value: emitteryMethodCaller(methodName)
});
}
return target;
};
}
static get isDebugEnabled() {
if (typeof globalThis.process.env !== "object") {
return isGlobalDebugEnabled;
}
const { env } = globalThis.process ?? { env: {} };
return env.DEBUG === "emittery" || env.DEBUG === "*" || isGlobalDebugEnabled;
}
static set isDebugEnabled(newValue) {
isGlobalDebugEnabled = newValue;
}
constructor(options = {}) {
anyMap.set(this, /* @__PURE__ */ new Set());
eventsMap.set(this, /* @__PURE__ */ new Map());
producersMap.set(this, /* @__PURE__ */ new Map());
producersMap.get(this).set(anyProducer, /* @__PURE__ */ new Set());
this.debug = options.debug ?? {};
if (this.debug.enabled === void 0) {
this.debug.enabled = false;
}
if (!this.debug.logger) {
this.debug.logger = (type, debugName, eventName, eventData) => {
try {
eventData = JSON.stringify(eventData);
} catch {
eventData = `Object with the following keys failed to stringify: ${Object.keys(eventData).join(",")}`;
}
if (typeof eventName === "symbol" || typeof eventName === "number") {
eventName = eventName.toString();
}
const currentTime = /* @__PURE__ */ new Date();
const logTime = `${currentTime.getHours()}:${currentTime.getMinutes()}:${currentTime.getSeconds()}.${currentTime.getMilliseconds()}`;
console.log(`[${logTime}][emittery:${type}][${debugName}] Event Name: ${eventName}
data: ${eventData}`);
};
}
}
logIfDebugEnabled(type, eventName, eventData) {
if (Emittery.isDebugEnabled || this.debug.enabled) {
this.debug.logger(type, this.debug.name, eventName, eventData);
}
}
on(eventNames, listener, { signal } = {}) {
assertListener(listener);
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
for (const eventName of eventNames) {
assertEventName(eventName);
let set = getListeners(this, eventName);
if (!set) {
set = /* @__PURE__ */ new Set();
const events = eventsMap.get(this);
events.set(eventName, set);
}
set.add(listener);
this.logIfDebugEnabled("subscribe", eventName, void 0);
if (!isMetaEvent(eventName)) {
emitMetaEvent(this, listenerAdded, { eventName, listener });
}
}
const off = () => {
this.off(eventNames, listener);
signal?.removeEventListener("abort", off);
};
signal?.addEventListener("abort", off, { once: true });
if (signal?.aborted) {
off();
}
return off;
}
off(eventNames, listener) {
assertListener(listener);
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
for (const eventName of eventNames) {
assertEventName(eventName);
const set = getListeners(this, eventName);
if (set) {
set.delete(listener);
if (set.size === 0) {
const events = eventsMap.get(this);
events.delete(eventName);
}
}
this.logIfDebugEnabled("unsubscribe", eventName, void 0);
if (!isMetaEvent(eventName)) {
emitMetaEvent(this, listenerRemoved, { eventName, listener });
}
}
}
once(eventNames) {
let off_;
const promise = new Promise((resolve) => {
off_ = this.on(eventNames, (data) => {
off_();
resolve(data);
});
});
promise.off = off_;
return promise;
}
events(eventNames) {
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
for (const eventName of eventNames) {
assertEventName(eventName);
}
return iterator(this, eventNames);
}
async emit(eventName, eventData) {
assertEventName(eventName);
if (isMetaEvent(eventName) && !canEmitMetaEvents) {
throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");
}
this.logIfDebugEnabled("emit", eventName, eventData);
enqueueProducers(this, eventName, eventData);
const listeners = getListeners(this, eventName) ?? /* @__PURE__ */ new Set();
const anyListeners = anyMap.get(this);
const staticListeners = [...listeners];
const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners];
await resolvedPromise;
await Promise.all([
...staticListeners.map(async (listener) => {
if (listeners.has(listener)) {
return listener(eventData);
}
}),
...staticAnyListeners.map(async (listener) => {
if (anyListeners.has(listener)) {
return listener(eventName, eventData);
}
})
]);
}
async emitSerial(eventName, eventData) {
assertEventName(eventName);
if (isMetaEvent(eventName) && !canEmitMetaEvents) {
throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");
}
this.logIfDebugEnabled("emitSerial", eventName, eventData);
const listeners = getListeners(this, eventName) ?? /* @__PURE__ */ new Set();
const anyListeners = anyMap.get(this);
const staticListeners = [...listeners];
const staticAnyListeners = [...anyListeners];
await resolvedPromise;
for (const listener of staticListeners) {
if (listeners.has(listener)) {
await listener(eventData);
}
}
for (const listener of staticAnyListeners) {
if (anyListeners.has(listener)) {
await listener(eventName, eventData);
}
}
}
onAny(listener, { signal } = {}) {
assertListener(listener);
this.logIfDebugEnabled("subscribeAny", void 0, void 0);
anyMap.get(this).add(listener);
emitMetaEvent(this, listenerAdded, { listener });
const offAny = () => {
this.offAny(listener);
signal?.removeEventListener("abort", offAny);
};
signal?.addEventListener("abort", offAny, { once: true });
if (signal?.aborted) {
offAny();
}
return offAny;
}
anyEvent() {
return iterator(this);
}
offAny(listener) {
assertListener(listener);
this.logIfDebugEnabled("unsubscribeAny", void 0, void 0);
emitMetaEvent(this, listenerRemoved, { listener });
anyMap.get(this).delete(listener);
}
clearListeners(eventNames) {
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
for (const eventName of eventNames) {
this.logIfDebugEnabled("clear", eventName, void 0);
if (isEventKeyType(eventName)) {
const set = getListeners(this, eventName);
if (set) {
set.clear();
}
const producers = getEventProducers(this, eventName);
if (producers) {
for (const producer of producers) {
producer.finish();
}
producers.clear();
}
} else {
anyMap.get(this).clear();
for (const [eventName2, listeners] of eventsMap.get(this).entries()) {
listeners.clear();
eventsMap.get(this).delete(eventName2);
}
for (const [eventName2, producers] of producersMap.get(this).entries()) {
for (const producer of producers) {
producer.finish();
}
producers.clear();
producersMap.get(this).delete(eventName2);
}
}
}
}
listenerCount(eventNames) {
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
let count = 0;
for (const eventName of eventNames) {
if (isEventKeyType(eventName)) {
count += anyMap.get(this).size + (getListeners(this, eventName)?.size ?? 0) + (getEventProducers(this, eventName)?.size ?? 0) + (getEventProducers(this)?.size ?? 0);
continue;
}
if (eventName !== void 0) {
assertEventName(eventName);
}
count += anyMap.get(this).size;
for (const value of eventsMap.get(this).values()) {
count += value.size;
}
for (const value of producersMap.get(this).values()) {
count += value.size;
}
}
return count;
}
bindMethods(target, methodNames) {
if (typeof target !== "object" || target === null) {
throw new TypeError("`target` must be an object");
}
methodNames = defaultMethodNamesOrAssert(methodNames);
for (const methodName of methodNames) {
if (target[methodName] !== void 0) {
throw new Error(`The property \`${methodName}\` already exists on \`target\``);
}
Object.defineProperty(target, methodName, {
enumerable: false,
value: this[methodName].bind(this)
});
}
}
}
const allEmitteryMethods = Object.getOwnPropertyNames(Emittery.prototype).filter((v2) => v2 !== "constructor");
Object.defineProperty(Emittery, "listenerAdded", {
value: listenerAdded,
writable: false,
enumerable: true,
configurable: false
});
Object.defineProperty(Emittery, "listenerRemoved", {
value: listenerRemoved,
writable: false,
enumerable: true,
configurable: false
});
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
function getDefaultExportFromCjs(x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
}
var bufferUtil$1 = { exports: {} };
const BINARY_TYPES$2 = ["nodebuffer", "arraybuffer", "fragments"];
const hasBlob$1 = typeof Blob !== "undefined";
if (hasBlob$1) BINARY_TYPES$2.push("blob");
var constants = {
BINARY_TYPES: BINARY_TYPES$2,
EMPTY_BUFFER: Buffer.alloc(0),
GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
hasBlob: hasBlob$1,
kForOnEventAttribute: Symbol("kIsForOnEventAttribute"),
kListener: Symbol("kListener"),
kStatusCode: Symbol("status-code"),
kWebSocket: Symbol("websocket"),
NOOP: () => {
}
};
var unmask$1;
var mask;
const { EMPTY_BUFFER: EMPTY_BUFFER$3 } = constants;
const FastBuffer$2 = Buffer[Symbol.species];
function concat$1(list, totalLength) {
if (list.length === 0) return EMPTY_BUFFER$3;
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$2(target.buffer, target.byteOffset, offset);
}
return target;
}
function _mask(source, mask2, output, offset, length) {
for (let i = 0; i < length; i++) {
output[offset + i] = source[i] ^ mask2[i & 3];
}
}
function _unmask(buffer, mask2) {
for (let i = 0; i < buffer.length; i++) {
buffer[i] ^= mask2[i & 3];
}
}
function toArrayBuffer$1(buf) {
if (buf.length === buf.buffer.byteLength) {
return buf.buffer;
}
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
}
function toBuffer$2(data) {
toBuffer$2.readOnly = true;
if (Buffer.isBuffer(data)) return data;
let buf;
if (data instanceof ArrayBuffer) {
buf = new FastBuffer$2(data);
} else if (ArrayBuffer.isView(data)) {
buf = new FastBuffer$2(data.buffer, data.byteOffset, data.byteLength);
} else {
buf = Buffer.from(data);
toBuffer$2.readOnly = false;
}
return buf;
}
bufferUtil$1.exports = {
concat: concat$1,
mask: _mask,
toArrayBuffer: toArrayBuffer$1,
toBuffer: toBuffer$2,
unmask: _unmask
};
if (!process.env.WS_NO_BUFFER_UTIL) {
try {
const bufferUtil2 = require("bufferutil");
mask = bufferUtil$1.exports.mask = function(source, mask2, output, offset, length) {
if (length < 48) _mask(source, mask2, output, offset, length);
else bufferUtil2.mask(source, mask2, output, offset, length);
};
unmask$1 = bufferUtil$1.exports.unmask = function(buffer, mask2) {
if (buffer.length < 32) _unmask(buffer, mask2);
else bufferUtil2.unmask(buffer, mask2);
};
} catch (e) {
}
}
var bufferUtilExports = bufferUtil$1.exports;
const kDone = Symbol("kDone");
const kRun = Symbol("kRun");
let Limiter$1 = class Limiter {
/**
* 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]);
}
}
};
var limiter = Limiter$1;
const zlib = require$$0;
const bufferUtil = bufferUtilExports;
const Limiter2 = limiter;
const { kStatusCode: kStatusCode$2 } = constants;
const FastBuffer$1 = 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$1 = Symbol("error");
let zlibLimiter;
let PerMessageDeflate$4 = class PerMessageDeflate {
/**
* 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|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
* @param {Boolean} [isServer=false] Create the instance in either server or
* client mode
* @param {Number} [maxPayload=0] The maximum allowed message length
*/
constructor(options, isServer, maxPayload) {
this._maxPayload = maxPayload | 0;
this._options = options || {};
this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024;
this._isServer = !!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 Limiter2(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(
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$1];
if (err) {
this._inflate.close();
this._inflate = null;
callback(err);
return;
}
const data2 = 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, data2);
});
}
/**
* 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 data2 = bufferUtil.concat(
this._deflate[kBuffers],
this._deflate[kTotalLength]
);
if (fin) {
data2 = new FastBuffer$1(data2.buffer, data2.byteOffset, data2.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, data2);
});
}
};
var permessageDeflate = PerMessageDeflate$4;
function deflateOnData(chunk) {
this[kBuffers].push(chunk);
this[kTotalLength] += chunk.length;
}
function inflateOnData(chunk) {
this[kTotalLength] += chunk.length;
if (this[kPerMessageDeflate]._maxPayload < 1 || this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload) {
this[kBuffers].push(chunk);
return;
}
this[kError$1] = new RangeError("Max payload size exceeded");
this[kError$1].code = "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH";
this[kError$1][kStatusCode$2] = 1009;
this.removeListener("data", inflateOnData);
this.reset();
}
function inflateOnError(err) {
this[kPerMessageDeflate]._inflate = null;
err[kStatusCode$2] = 1007;
this[kCallback](err);
}
var validation = { exports: {} };
var utf8Validate = { exports: {} };
function commonjsRequire(path2) {
throw new Error('Could not dynamically require "' + path2 + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
}
var nodeGypBuild$1 = { exports: {} };
var nodeGypBuild;
var hasRequiredNodeGypBuild$1;
function requireNodeGypBuild$1() {
if (hasRequiredNodeGypBuild$1) return nodeGypBuild;
hasRequiredNodeGypBuild$1 = 1;
var fs$1 = fs;
var path$1 = path;
var os2 = require$$2;
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : commonjsRequire;
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 || os2.arch();
var platform = process.env.npm_config_platform || os2.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];
nodeGypBuild = 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" : ""
// eslint-disable-line
].filter(Boolean).join(" ");
throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
function resolve(dir2) {
var tuples = readdirSync(path$1.join(dir2, "prebuilds")).map(parseTuple);
var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
if (!tuple) return;
var prebuilds = path$1.join(dir2, "prebuilds", tuple.name);
var parsed = readdirSync(prebuilds).map(parseTags);
var candidates = parsed.filter(matchTags(runtime, abi));
var winner = candidates.sort(compareTags(runtime))[0];
if (winner) return path$1.join(prebuilds, winner.file);
}
};
function readdirSync(dir) {
try {
return fs$1.readdirSync(dir);
} catch (err) {
return [];
}
}
function getFirst(dir, filter) {
var files2 = readdirSync(dir).filter(filter);
return files2[0] && path$1.join(dir, files2[0]);
}
function matchBuild(name) {
return /\.node$/.test(name);
}
function parseTuple(name) {
var arr = name.split("-");
if (arr.length !== 2) return;
var platform2 = arr[0];
var architectures = arr[1].split("+");
if (!platform2) return;
if (!architectures.length) return;
if (!architectures.every(Boolean)) return;
return { name, platform: platform2, architectures };
}
function matchTuple(platform2, arch2) {
return function(tuple) {
if (tuple == null) return false;
if (tuple.platform !== platform2) return false;
return tuple.architectures.includes(arch2);
};
}
function compareTuples(a, b) {
return a.architectures.length - b.architectures.length;
}
function parseTags(file) {
var arr = file.split(".");
var extension2 = arr.pop();
var tags = { file, specificity: 0 };
if (extension2 !== "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(runtime2, abi2) {
return function(tags) {
if (tags == null) return false;
if (tags.runtime && tags.runtime !== runtime2 && !runtimeAgnostic(tags)) return false;
if (tags.abi && tags.abi !== abi2 && !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(runtime2) {
return function(a, b) {
if (a.runtime !== b.runtime) {
return a.runtime === runtime2 ? -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(platform2) {
return platform2 === "linux" && fs$1.existsSync("/etc/alpine-release");
}
load.parseTags = parseTags;
load.matchTags = matchTags;
load.compareTags = compareTags;
load.parseTuple = parseTuple;
load.matchTuple = matchTuple;
load.compareTuples = compareTuples;
return nodeGypBuild;
}
var hasRequiredNodeGypBuild;
function requireNodeGypBuild() {
if (hasRequiredNodeGypBuild) return nodeGypBuild$1.exports;
hasRequiredNodeGypBuild = 1;
const runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : commonjsRequire;
if (typeof runtimeRequire.addon === "function") {
nodeGypBuild$1.exports = runtimeRequire.addon.bind(runtimeRequire);
} else {
nodeGypBuild$1.exports = requireNodeGypBuild$1();
}
return nodeGypBuild$1.exports;
}
var fallback;
var hasRequiredFallback;
function requireFallback() {
if (hasRequiredFallback) return fallback;
hasRequiredFallback = 1;
function isValidUTF82(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 || // overlong
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 || // overlong
buf[i] === 244 && buf[i + 1] > 143 || buf[i] > 244) {
return false;
}
i += 4;
} else {
return false;
}
}
return true;
}
fallback = isValidUTF82;
return fallback;
}
var hasRequiredUtf8Validate;
function requireUtf8Validate() {
if (hasRequiredUtf8Validate) return utf8Validate.exports;
hasRequiredUtf8Validate = 1;
try {
utf8Validate.exports = requireNodeGypBuild()(__dirname);
} catch (e) {
utf8Validate.exports = requireFallback();
}
return utf8Validate.exports;
}
var isValidUTF8_1;
const { isUtf8 } = require$$0$1;
const { hasBlob } = constants;
const tokenChars$2 = [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
// 0 - 15
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
// 16 - 31
0,
1,
0,
1,
1,
1,
1,
1,
0,
0,
1,
1,
0,
1,
1,
0,
// 32 - 47
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
// 48 - 63
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
// 64 - 79
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
1,
1,
// 80 - 95
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
// 96 - 111
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
1,
0,
1,
0
// 112 - 127
];
function isValidStatusCode$2(code) {
return code >= 1e3 && code <= 1014 && code !== 1004 && code !== 1005 && code !== 1006 || code >= 3e3 && code <= 4999;
}
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 || // Overlong
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 || // Overlong
buf[i] === 244 && buf[i + 1] > 143 || buf[i] > 244) {
return false;
}
i += 4;
} else {
return false;
}
}
return true;
}
function isBlob$2(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");
}
validation.exports = {
isBlob: isBlob$2,
isValidStatusCode: isValidStatusCode$2,
isValidUTF8: _isValidUTF8,
tokenChars: tokenChars$2
};
if (isUtf8) {
isValidUTF8_1 = validation.exports.isValidUTF8 = function(buf) {
return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);
};
} else if (!process.env.WS_NO_UTF_8_VALIDATE) {
try {
const isValidUTF82 = requireUtf8Validate();
isValidUTF8_1 = validation.exports.isValidUTF8 = function(buf) {
return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF82(buf);
};
} catch (e) {
}
}
var validationExports = validation.exports;
const { Writable } = require$$0$2;
const PerMessageDeflate$3 = permessageDeflate;
const {
BINARY_TYPES: BINARY_TYPES$1,
EMPTY_BUFFER: EMPTY_BUFFER$2,
kStatusCode: kStatusCode$1,
kWebSocket: kWebSocket$3
} = constants;
const { concat, toArrayBuffer, unmask } = bufferUtilExports;
const { isValidStatusCode: isValidStatusCode$1, isValidUTF8 } = validationExports;
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;
let Receiver$1 = class Receiver extends Writable {
/**
* 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.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$1[0];
this._extensions = options.extensions || {};
this._isServer = !!options.isServer;
this._maxPayload = options.maxPayload | 0;
this._skipUTF8Validation = !!options.skipUTF8Validation;
this[kWebSocket$3] = 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._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();
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) {
const error = this.createError(
RangeError,
"RSV2 and RSV3 must be clear",
true,
1002,
"WS_ERR_UNEXPECTED_RSV_2_3"
);
cb(error);
return;
}
const compressed = (buf[0] & 64) === 64;
if (compressed && !this._extensions[PerMessageDeflate$3.extensionName]) {
const error = this.createError(
RangeError,
"RSV1 must be clear",
true,
1002,
"WS_ERR_UNEXPECTED_RSV_1"
);