| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _nodeNet = _interopRequireDefault(require("node:net"));
- var _nodeOs = _interopRequireDefault(require("node:os"));
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
- /*
- * Based on the packages get-port https://www.npmjs.com/package/get-port
- * and portfinder https://www.npmjs.com/package/portfinder
- * The code structure is similar to get-port, but it searches
- * ports deterministically like portfinder
- */
- const minPort = 1024;
- const maxPort = 65_535;
- /**
- * @returns {Set<string | undefined>} local hosts
- */
- const getLocalHosts = () => {
- const interfaces = _nodeOs.default.networkInterfaces();
- // Add undefined value for createServer function to use default host,
- // and default IPv4 host in case createServer defaults to IPv6.
- const results = new Set([undefined, "0.0.0.0"]);
- for (const _interface of Object.values(interfaces)) {
- if (_interface) {
- for (const config of _interface) {
- results.add(config.address);
- }
- }
- }
- return results;
- };
- /**
- * @param {number} basePort base port
- * @param {string | undefined} host host
- * @returns {Promise<number>} resolved port
- */
- const checkAvailablePort = (basePort, host) => new Promise((resolve, reject) => {
- const server = _nodeNet.default.createServer();
- server.unref();
- server.on("error", reject);
- server.listen(basePort, host, () => {
- // Next line should return AddressInfo because we're calling it after listen() and before close()
- const {
- port
- } = /** @type {import("net").AddressInfo} */
- server.address();
- server.close(() => {
- resolve(port);
- });
- });
- });
- /**
- * @param {number} port port
- * @param {Set<string | undefined>} hosts hosts
- * @returns {Promise<number>} resolved port
- */
- const getAvailablePort = async (port, hosts) => {
- /**
- * Errors that mean that host is not available.
- * @type {Set<string | undefined>}
- */
- const nonExistentInterfaceErrors = new Set(["EADDRNOTAVAIL", "EINVAL"]);
- /* Check if the post is available on every local host name */
- for (const host of hosts) {
- try {
- await checkAvailablePort(port, host);
- } catch (error) {
- /* We throw an error only if the interface exists */
- if (!nonExistentInterfaceErrors.has(/** @type {NodeJS.ErrnoException} */error.code)) {
- throw error;
- }
- }
- }
- return port;
- };
- /**
- * @param {number} basePort base port
- * @param {string=} host host
- * @returns {Promise<number>} resolved port
- */
- async function getPorts(basePort, host) {
- if (basePort < minPort || basePort > maxPort) {
- throw new Error(`Port number must lie between ${minPort} and ${maxPort}`);
- }
- let port = basePort;
- const localhosts = getLocalHosts();
- const hosts = host && !localhosts.has(host) ? new Set([host]) :
- /* If the host is equivalent to localhost
- we need to check every equivalent host
- else the port might falsely appear as available
- on some operating systems */
- localhosts;
- /** @type {Set<string | undefined>} */
- const portUnavailableErrors = new Set(["EADDRINUSE", "EACCES"]);
- while (port <= maxPort) {
- try {
- const availablePort = await getAvailablePort(port, hosts);
- return availablePort;
- } catch (error) {
- /* Try next port if port is busy; throw for any other error */
- if (!portUnavailableErrors.has(/** @type {NodeJS.ErrnoException} */error.code)) {
- throw error;
- }
- port += 1;
- }
- }
- throw new Error("No available ports found");
- }
- var _default = exports.default = getPorts;
|