xkite-core
Version:
Core library for xkite application
166 lines (165 loc) • 5.86 kB
JavaScript
;
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 __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var deps_exports = {};
__export(deps_exports, {
default: () => deps_default,
portNumbers: () => portNumbers
});
module.exports = __toCommonJS(deps_exports);
var import_node_net = __toESM(require("node:net"), 1);
var import_node_os = __toESM(require("node:os"), 1);
var Locked = class extends Error {
constructor(port) {
super(`${port} is locked`);
}
};
var lockedPorts = {
old: new Set(),
young: new Set()
};
var releaseOldLockedPortsIntervalMs = 1e3 * 15;
var minPort = 1024;
var maxPort = 65535;
var interval;
var getLocalHosts = () => {
const interfaces = import_node_os.default.networkInterfaces();
const results = new Set([void 0, "0.0.0.0"]);
for (const _interface of Object.values(interfaces)) {
for (const config of _interface) {
results.add(config.address);
}
}
return results;
};
var checkAvailablePort = (options) => new Promise((resolve, reject) => {
const server = import_node_net.default.createServer();
server.unref();
server.on("error", reject);
server.listen(options, () => {
const { port } = server.address();
server.close(() => {
resolve(port);
});
});
});
var getAvailablePort = async (options, hosts) => {
if (options.host || options.port === 0) {
return checkAvailablePort(options);
}
for (const host of hosts) {
try {
await checkAvailablePort({ port: options.port, host });
}
catch (error) {
if (!["EADDRNOTAVAIL", "EINVAL"].includes(error.code)) {
throw error;
}
}
}
return options.port;
};
var portCheckSequence = function* (ports) {
if (ports) {
yield* ports;
}
yield 0;
};
async function getPorts(options) {
let ports;
let exclude = new Set();
if (options) {
if (options.port) {
ports = typeof options.port === "number" ? [options.port] : options.port;
}
if (options.exclude) {
const excludeIterable = options.exclude;
if (typeof excludeIterable[Symbol.iterator] !== "function") {
throw new TypeError("The `exclude` option must be an iterable.");
}
for (const element of excludeIterable) {
if (typeof element !== "number") {
throw new TypeError("Each item in the `exclude` option must be a number corresponding to the port you want excluded.");
}
if (!Number.isSafeInteger(element)) {
throw new TypeError(`Number ${element} in the exclude option is not a safe integer and can't be used`);
}
}
exclude = new Set(excludeIterable);
}
}
if (interval === void 0) {
interval = setInterval(() => {
lockedPorts.old = lockedPorts.young;
lockedPorts.young = new Set();
}, releaseOldLockedPortsIntervalMs);
if (interval.unref) {
interval.unref();
}
}
const hosts = getLocalHosts();
for (const port of portCheckSequence(ports)) {
try {
if (exclude.has(port)) {
continue;
}
let availablePort = await getAvailablePort({ ...options, port }, hosts);
while (lockedPorts.old.has(availablePort) || lockedPorts.young.has(availablePort)) {
if (port !== 0) {
throw new Locked(port);
}
availablePort = await getAvailablePort({ ...options, port }, hosts);
}
lockedPorts.young.add(availablePort);
return availablePort;
}
catch (error) {
if (!["EADDRINUSE", "EACCES"].includes(error.code) && !(error instanceof Locked)) {
throw error;
}
}
}
throw new Error("No available ports found");
}
function portNumbers(from, to) {
if (!Number.isInteger(from) || !Number.isInteger(to)) {
throw new TypeError("`from` and `to` must be integer numbers");
}
if (from < minPort || from > maxPort) {
throw new RangeError(`'from' must be between ${minPort} and ${maxPort}`);
}
if (to < minPort || to > maxPort) {
throw new RangeError(`'to' must be between ${minPort} and ${maxPort}`);
}
if (from > to) {
throw new RangeError("`to` must be greater than or equal to `from`");
}
const generator = function* (from2, to2) {
for (let port = from2; port <= to2; port++) {
yield port;
}
};
return generator(from, to);
}
var deps_default = getPorts;
0 && (module.exports = {
portNumbers
});