78 lines
2.3 KiB
JavaScript
78 lines
2.3 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
exports.findFreePorts = findFreePorts;
|
|
exports.isFreePort = isFreePort;
|
|
var _os = _interopRequireDefault(require("os"));
|
|
var _net = _interopRequireDefault(require("net"));
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
const MIN_PORT = 1025;
|
|
const MAX_PORT = 65535;
|
|
const DEFAULT_JOB_COUNT = _os.default.cpus().length;
|
|
function clamp(value, min, max) {
|
|
if (value < min) return min;
|
|
if (value > max) return max;
|
|
return value;
|
|
}
|
|
async function findFreePorts(count = 1, {
|
|
endPort = MAX_PORT,
|
|
startPort = MIN_PORT,
|
|
jobCount = DEFAULT_JOB_COUNT,
|
|
isFree = isFreePort
|
|
} = {}) {
|
|
if (count > endPort - startPort) {
|
|
throw new Error(`Could not find free ports: the range of allowed ports is not large enough for the requested amount of ports to find.`);
|
|
}
|
|
const portInterval = Math.ceil((endPort - startPort) / jobCount);
|
|
const ports = [];
|
|
const jobPromises = [];
|
|
for (let i = 0; i < jobCount; i++) {
|
|
jobPromises.push(scanRange(startPort + portInterval * i, Math.min(endPort, startPort + portInterval * (i + 1))));
|
|
}
|
|
await Promise.all(jobPromises);
|
|
if (ports.length < count) {
|
|
throw new Error(`Could not find free ports: there were not enough ports available.`);
|
|
}
|
|
return ports;
|
|
async function scanRange(startPort, endPort) {
|
|
for (let port = startPort; port < endPort; port++) {
|
|
if (ports.length >= count) {
|
|
break;
|
|
}
|
|
if (await isFree(port)) {
|
|
if (ports.length >= count) {
|
|
break;
|
|
}
|
|
ports.push(port);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function isFreePort(port) {
|
|
return new Promise((accept, reject) => {
|
|
const sock = _net.default.createConnection(port);
|
|
sock.once('connect', () => {
|
|
sock.end();
|
|
accept(false);
|
|
});
|
|
sock.once('error', e => {
|
|
sock.destroy();
|
|
if (e.code === 'ECONNREFUSED') {
|
|
accept(true);
|
|
} else {
|
|
reject(e);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
var _default = findFreePorts;
|
|
exports.default = _default;
|
|
if (typeof module.exports !== 'undefined') {
|
|
module.exports = findFreePorts;
|
|
findFreePorts.findFreePorts = findFreePorts;
|
|
findFreePorts.isFreePort = isFreePort;
|
|
}
|
|
//# sourceMappingURL=index.js.map
|