@shopify/cli-kit
Version:
A set of utilities, interfaces, and models that are common across all the platform features
72 lines • 2.97 kB
JavaScript
import { sleep } from './system.js';
import { AbortError } from './error.js';
import { outputDebug, outputContent, outputToken } from '../../public/node/output.js';
import * as port from 'get-port-please';
const obtainedRandomPorts = new Set();
/**
* Returns an available port in the current environment.
*
* @param preferredPort - Number of the preferred port to be used if available.
* @param options - Extra configuration for getting TCP ports.
* @returns A promise that resolves with an availabe port.
*/
export async function getAvailableTCPPort(preferredPort, options) {
if (preferredPort && (await checkPortAvailability(preferredPort))) {
outputDebug(outputContent `Port ${preferredPort.toString()} is free`);
return preferredPort;
}
outputDebug(outputContent `Getting a random port...`);
let randomPort = await retryOnError(() => port.getRandomPort(host()), options?.maxTries, options?.waitTimeInSeconds);
for (let i = 0; i < (options?.maxTries ?? 5); i++) {
if (!obtainedRandomPorts.has(randomPort)) {
break;
}
// eslint-disable-next-line no-await-in-loop
randomPort = await retryOnError(() => port.getRandomPort(host()), options?.maxTries, options?.waitTimeInSeconds);
}
outputDebug(outputContent `Random port obtained: ${outputToken.raw(`${randomPort}`)}`);
obtainedRandomPorts.add(randomPort);
return randomPort;
}
/**
* Checks if a port is available.
*
* @param portNumber - The port number to check.
* @returns A promise that resolves with a boolean indicating if the port is available.
*/
export async function checkPortAvailability(portNumber) {
return (await port.checkPort(portNumber, host())) === portNumber;
}
function host() {
// The get-port-please library does not work as expected when HOST env var is defined,
// so explicitly set the host to 0.0.0.0 to avoid conflicts
return process.env.HOST ? '0.0.0.0' : undefined;
}
/**
* Given a function, it runs it and retries in case of failiure up to the provided number of times.
*
* @param execute - The function to execute.
* @param maxTries - The maximum retries.
* @param waitTimeInSeconds - The time to wait between retries.
*/
async function retryOnError(execute, maxTries = 5, waitTimeInSeconds = 1) {
let retryCount = 1;
while (true) {
try {
// eslint-disable-next-line no-await-in-loop
return await execute();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}
catch (error) {
if (retryCount++ < maxTries) {
outputDebug(outputContent `Unknown problem getting a random port: ${error.message}`);
// eslint-disable-next-line no-await-in-loop
await sleep(waitTimeInSeconds);
}
else {
throw new AbortError(error.message);
}
}
}
}
//# sourceMappingURL=tcp.js.map