UNPKG

@dynatrace/devkit

Version:

The Dynatrace App Toolkit utilities for writing and testing migrations.

106 lines (105 loc) 3.28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.findPortInRange = findPortInRange; exports.isUsed = isUsed; exports.runOnUnusedPort = runOnUnusedPort; const net_1 = require("net"); /** * @internal Only for the use of DevXp * Util to get a free port to run tests on. */ async function findPortInRange(host, startPort, endPort) { let port = startPort; while (endPort ? port <= endPort : true) { if (!(await isUsed(host, port))) { return port; } else { port++; if (endPort && port > endPort) { throw new Error('All ports are taken!'); } } } } /** * @internal Only for the use of DevXp * Util to check if a port is used or not */ async function isUsed(host, port) { return new Promise((resolve) => { const server = (0, net_1.createServer)(); server.once('error', () => resolve(true)); server.once('listening', function () { server.close(() => { resolve(false); }); }); server.listen(port, host); }); } /** * @internal Only for the use of DevXp * Util to write code that depends on a port being unused. Tries to run * the specified code on a specified port and retries with next port (<= options.endPort) * if it fails due to the port being bound already. * @param run code to run that depends on a port being unused. * @param startPort port that should be used for the first try. * @param options further options. * @returns */ async function runOnUnusedPort(run, startPort, options) { // If specified range is an array, make a copy in order to not // modify original array. let range; if (options && Array.isArray(options.range)) { range = [...options.range]; } else { range = options?.range; } // Start with specified port let port = startPort; while (port) { try { const t = await run(port); return t; } catch (error) { if ((options?.errorMessage && error.message.includes(options?.errorMessage)) || error.message.includes('EADDRINUSE') || error.message.includes('EACCES')) { if (options?.onUsedCallback) { options.onUsedCallback(port); } } else { throw error; } } port = getNextPort(port, range); } throw Error(options?.displayMessage ?? 'Could not find a free port!'); } /** * Helper function that tries to find the next port to try. * Attention: Has a side effect on range as shift changes the range if it is a number[] */ function getNextPort(port, range) { if (!range) { // If nothing specified, try the next port return port + 1; } else { if (typeof range === 'number') { // If range is specified by a single number check if the current port is still // smaller than upper limit. return port < range ? port + 1 : undefined; } else { // Returns and removes the first element of range return range.shift(); } } }